From 86cf5e704dd1321f524ff0063bd2ec371be2abc3 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 25 Aug 2022 09:01:11 +0200 Subject: [PATCH 1/5] reworking gNB PUCCH scheduling --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 10 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 52 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 521 ++++++------------ openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 7 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 6 +- 5 files changed, 231 insertions(+), 365 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 5cf4bc295c..ac9b86e5c9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -215,9 +215,8 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // Schedule CSI-RS transmission nr_csirs_scheduling(module_idP, frame, slot, nr_slots_per_frame[*scc->ssbSubcarrierSpacing]); - // Schedule CSI measurement reporting: check in slot 0 for the whole frame - if (slot == 0) - nr_csi_meas_reporting(module_idP, frame, slot); + // Schedule CSI measurement reporting + nr_csi_meas_reporting(module_idP, frame, slot); // Schedule SRS: check in slot 0 for the whole frame if (slot == 0) @@ -237,10 +236,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, nr_schedule_ue_spec(module_idP, frame, slot); stop_meas(&gNB->schedule_dlsch); - nr_schedule_pucch(RC.nrmac[module_idP], frame, slot); + nr_sr_reporting(RC.nrmac[module_idP], frame, slot, module_idP); - // This schedule SR after PUCCH for multiplexing - nr_sr_reporting(RC.nrmac[module_idP], frame, slot); + nr_schedule_pucch(RC.nrmac[module_idP], frame, slot); stop_meas(&RC.nrmac[module_idP]->eNB_scheduler); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 690bb2211b..66f431946d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1087,7 +1087,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, pucch_pdu->cyclic_prefix = (current_BWP->cyclicprefix==NULL) ? 0 : *current_BWP->cyclicprefix; NR_PUCCH_Config_t *pucch_Config = current_BWP->pucch_Config; - if (r_pucch<0 || pucch_Config){ + if (r_pucch<0 || pucch_Config) { LOG_D(NR_MAC,"pucch_acknak: Filling dedicated configuration for PUCCH\n"); AssertFatal(pucch_Config->resourceSetToAddModList!=NULL, @@ -2375,6 +2375,17 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, else UL_BWP->pucch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup; + UL_BWP->max_fb_time = 0; + if(DL_BWP->dci_format != NR_DL_DCI_FORMAT_1_0 && + UL_BWP->pucch_Config) { + for (int i=0; ipucch_Config->dl_DataToUL_ACK->list.count; i++) { + if(*UL_BWP->pucch_Config->dl_DataToUL_ACK->list.array[i] > UL_BWP->max_fb_time) + UL_BWP->max_fb_time = *UL_BWP->pucch_Config->dl_DataToUL_ACK->list.array[i]; + } + } + else + UL_BWP->max_fb_time = 8; // default value + if(UE) { // setting PDCCH related structures for sched_ctrl @@ -2410,6 +2421,8 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, if (UL_BWP->csi_MeasConfig) compute_csi_bitlen (UL_BWP->csi_MeasConfig, UE->csi_report_template); + set_sched_pucch_list(sched_ctrl, UL_BWP, scc); + } if(ra) { @@ -2456,6 +2469,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_RNTI_C, target_ss, false); + } void reset_srs_stats(NR_UE_info_t *UE) { @@ -2553,6 +2567,34 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf return (UE); } +void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, + NR_UE_UL_BWP_t *ul_bwp, + NR_ServingCellConfigCommon_t *scc) { + + const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; + const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs]; + const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; + const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; + + const int list_size = n_ul_slots_period << (ul_bwp->max_fb_time/nr_slots_period); + if(!sched_ctrl->sched_pucch) { + sched_ctrl->sched_pucch = malloc(list_size * sizeof(*sched_ctrl->sched_pucch)); + sched_ctrl->sched_pucch_size = list_size; + for(int i=0; isched_pucch[i]; + memset(curr_pucch, 0, sizeof(*curr_pucch)); + } + } + else if (list_size > sched_ctrl->sched_pucch_size) { + sched_ctrl->sched_pucch = realloc(sched_ctrl->sched_pucch, list_size * sizeof(*sched_ctrl->sched_pucch)); + for(int i=sched_ctrl->sched_pucch_size; isched_pucch[i]; + memset(curr_pucch, 0, sizeof(*curr_pucch)); + } + sched_ctrl->sched_pucch_size = list_size; + } +} + void create_dl_harq_list(NR_UE_sched_ctrl_t *sched_ctrl, const NR_PDSCH_ServingCellConfig_t *pdsch) { const int nrofHARQ = pdsch && pdsch->nrofHARQ_ProcessesForPDSCH ? @@ -2672,23 +2714,17 @@ uint8_t nr_get_tpc(int target, uint8_t cqi, int incr) { void get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config, nr_dci_format_t dci_format, - int *max_fb_time, uint8_t *pdsch_to_harq_feedback) { if (dci_format == NR_DL_DCI_FORMAT_1_0) { - for (int i=0; i<8; i++) { + for (int i=0; i<8; i++) pdsch_to_harq_feedback[i] = i+1; - if(pdsch_to_harq_feedback[i]>*max_fb_time) - *max_fb_time = pdsch_to_harq_feedback[i]; - } } else { AssertFatal(pucch_Config!=NULL,"pucch_Config shouldn't be null here\n"); if(pucch_Config->dl_DataToUL_ACK != NULL) { for (int i=0; i<8; i++) { pdsch_to_harq_feedback[i] = *pucch_Config->dl_DataToUL_ACK->list.array[i]; - if(pdsch_to_harq_feedback[i]>*max_fb_time) - *max_fb_time = pdsch_to_harq_feedback[i]; } } else diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index c347ea5bea..2c4166f261 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -45,8 +45,8 @@ static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac, const NR_sched_pucch_t *pucch, NR_UE_info_t* UE) { - nfapi_nr_ul_tti_request_t *future_ul_tti_req = - &nrmac->UL_tti_req_ahead[0][pucch->ul_slot]; + + nfapi_nr_ul_tti_request_t *future_ul_tti_req = &nrmac->UL_tti_req_ahead[0][pucch->ul_slot]; if (future_ul_tti_req->SFN != pucch->frame || future_ul_tti_req->Slot != pucch->ul_slot) LOG_W(MAC, "Current %d.%d : future UL_tti_req's frame.slot %4d.%2d does not match PUCCH %4d.%2d\n", @@ -55,6 +55,7 @@ static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac, future_ul_tti_req->Slot, pucch->frame, pucch->ul_slot); + // n_pdus is number of pdus, so, in the array, it is the index of the next free element if (future_ul_tti_req->n_pdus >= sizeofArray(future_ul_tti_req->pdus_list) ) { LOG_E(NR_MAC,"future_ul_tti_req->n_pdus %d is full, slot: %d, sr flag %d dropping request\n", @@ -139,22 +140,19 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac, UE_iterator(nrmac->UE_info.list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - const int n = sizeof(sched_ctrl->sched_pucch) / sizeof(*sched_ctrl->sched_pucch); - for (int i = 0; i < n; i++) { + for (int i = 0; i < sched_ctrl->sched_pucch_size; i++) { NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[i]; const uint16_t O_ack = curr_pucch->dai_c; const uint16_t O_csi = curr_pucch->csi_bits; const uint8_t O_sr = curr_pucch->sr_flag; - if (O_ack + O_csi + O_sr == 0 - || frameP != curr_pucch->frame - || slotP != curr_pucch->ul_slot) - continue; - - if (O_csi > 0) - LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %04x in %4d.%2d O_ack %d, O_sr %d, O_csi %d\n", - i,UE->rnti,curr_pucch->frame,curr_pucch->ul_slot,O_ack,O_sr,O_csi); - nr_fill_nfapi_pucch(nrmac, frameP, slotP, curr_pucch, UE); - memset(curr_pucch, 0, sizeof(*curr_pucch)); + if (curr_pucch->active == true && + frameP == curr_pucch->frame && + slotP == curr_pucch->ul_slot) { + LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %04x in %4d.%2d O_ack %d, O_sr %d, O_csi %d\n", + i,UE->rnti,curr_pucch->frame,curr_pucch->ul_slot,O_ack,O_sr,O_csi); + nr_fill_nfapi_pucch(nrmac, frameP, slotP, curr_pucch, UE); + memset(curr_pucch, 0, sizeof(*curr_pucch)); + } } } } @@ -186,14 +184,16 @@ void nr_csi_meas_reporting(int Mod_idP, if(pucchcsires->uplinkBandwidthPartId != ul_bwp->bwp_id) continue; + // we schedule CSI reporting max_fb_time slots in advance int period, offset; csi_period_offset(csirep, NULL, &period, &offset); - const int sched_slot = (period + offset) % n_slots_frame; + const int sched_slot = (slot + ul_bwp->max_fb_time) % n_slots_frame; + const int sched_frame = (frame + ((slot + ul_bwp->max_fb_time) / n_slots_frame)) % 1024; // prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214 - // preparation is done in first slot of tdd period - if (frame % (period / n_slots_frame) != offset / n_slots_frame) + if ((sched_frame*n_slots_frame + sched_slot - offset)%period != 0) continue; - LOG_D(NR_MAC, "CSI reporting in frame %d slot %d CSI report ID %ld\n", frame, sched_slot, csirep->reportConfigId); + + LOG_D(NR_MAC, "CSI reporting in frame %d slot %d CSI report ID %ld\n", sched_frame, sched_slot, csirep->reportConfigId); const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1 const int n = pucchresset->resourceList.list.count; @@ -206,17 +206,21 @@ void nr_csi_meas_reporting(int Mod_idP, // find free PUCCH that is in order with possibly existing PUCCH // schedulings (other CSI, SR) - NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[1]; - AssertFatal(curr_pucch->csi_bits == 0 - && !curr_pucch->sr_flag - && curr_pucch->dai_c == 0, - "PUCCH not free at index 1 for UE %04x\n", + NR_sched_pucch_t *curr_pucch = NULL; + for (int i=0; isched_pucch_size; i++) { + curr_pucch = &sched_ctrl->sched_pucch[i]; + if (!curr_pucch->active) + break; // found an available pucch structure + } + AssertFatal(curr_pucch, + "PUCCH structure not found for UE %04x\n", UE->rnti); curr_pucch->r_pucch = -1; - curr_pucch->frame = frame; + curr_pucch->frame = sched_frame; curr_pucch->ul_slot = sched_slot; curr_pucch->resource_indicator = res_index; curr_pucch->csi_bits += nr_get_csi_bitlen(UE->csi_report_template, csi_report_id); + curr_pucch->active = true; int bwp_start = ul_bwp->BWPStart; @@ -235,7 +239,7 @@ void nr_csi_meas_reporting(int Mod_idP, len = pucchres->format.choice.format2->nrofPRBs; mask = SL_to_bitmap(pucchres->format.choice.format2->startingSymbolIndex, pucchres->format.choice.format2->nrofSymbols); curr_pucch->simultaneous_harqcsi = pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI; - LOG_D(NR_MAC,"%d.%d Allocating PUCCH format 2, startPRB %d, nPRB %d, simulHARQ %d, num_bits %d\n", frame, sched_slot,start,len,curr_pucch->simultaneous_harqcsi,curr_pucch->csi_bits); + LOG_D(NR_MAC,"%d.%d Allocating PUCCH format 2, startPRB %d, nPRB %d, simulHARQ %d, num_bits %d\n", sched_frame, sched_slot,start,len,curr_pucch->simultaneous_harqcsi,curr_pucch->csi_bits); break; case NR_PUCCH_Resource__format_PR_format3: len = pucchres->format.choice.format3->nrofPRBs; @@ -252,7 +256,7 @@ void nr_csi_meas_reporting(int Mod_idP, // verify resources are free for (int i = start; i < start + len; ++i) { if((vrb_map_UL[i+bwp_start] & mask) != 0) { - LOG_E(NR_MAC, "%4d.%2d VRB MAP in %4d.%2d not free. Can't schedule CSI reporting on PUCCH.\n", frame, slot, frame, sched_slot); + LOG_E(NR_MAC, "%4d.%2d VRB MAP in %4d.%2d not free. Can't schedule CSI reporting on PUCCH.\n", frame, slot, sched_frame, sched_slot); memset(curr_pucch, 0, sizeof(*curr_pucch)); } else @@ -993,26 +997,17 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, } } -bool test_acknack_vrb_occupation(NR_UE_sched_ctrl_t *sched_ctrl, - NR_sched_pucch_t *pucch, - uint16_t *vrb_map_UL, - const NR_ServingCellConfigCommon_t *scc, - NR_PUCCH_Config_t *pucch_Config, - int r_pucch, - int bwp_start, - int bwp_size) { +bool test_pucch0_vrb_occupation(NR_UE_sched_ctrl_t *sched_ctrl, + NR_sched_pucch_t *pucch, + uint16_t *vrb_map_UL, + const NR_ServingCellConfigCommon_t *scc, + NR_PUCCH_Config_t *pucch_Config, + int r_pucch, + int bwp_start, + int bwp_size) { // We assume initial cyclic shift is always 0 so different pucch resources can't overlap - NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[1]; - if (csi_pucch && - csi_pucch->csi_bits > 0 && - csi_pucch->frame == pucch->frame && - csi_pucch->ul_slot == pucch->ul_slot && - csi_pucch->simultaneous_harqcsi && - (csi_pucch->csi_bits + csi_pucch->dai_c) < 11) - return true; // available resources for csi_pucch already verified - if(r_pucch<0){ const NR_PUCCH_Resource_t *resource = pucch_Config->resourceToAddModList->list.array[0]; DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0); @@ -1049,15 +1044,15 @@ bool test_acknack_vrb_occupation(NR_UE_sched_ctrl_t *sched_ctrl, } // this function returns an index to NR_sched_pucch structure -// currently this structure contains PUCCH0 at index 0 and PUCCH2 at index 1 // if the function returns -1 it was not possible to schedule acknack -// when current pucch is ready to be scheduled nr_fill_nfapi_pucch is called int nr_acknack_scheduling(int mod_id, NR_UE_info_t *UE, frame_t frame, sub_frame_t slot, int r_pucch, - int is_common) { + int is_common) +{ + const int CC_id = 0; const int minfbtime = RC.nrmac[mod_id]->minRXTXTIMEpdsch; const NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels[CC_id].ServingCellConfigCommon; @@ -1066,10 +1061,8 @@ int nr_acknack_scheduling(int mod_id, const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; AssertFatal(tdd || RC.nrmac[mod_id]->common_channels[CC_id].frame_type == FDD, "Dynamic TDD not handled yet\n"); const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int next_ul_slot = tdd ? tdd->nrofDownlinkSlots + nr_slots_period * (slot / nr_slots_period) : slot + minfbtime; const int first_ul_slot_period = tdd ? tdd->nrofDownlinkSlots : 0; - /* for the moment, we consider: * * only pucch_sched[0] holds HARQ (and SR) * * we do not multiplex with CSI, which is always in pucch_sched[2] @@ -1082,247 +1075,110 @@ int nr_acknack_scheduling(int mod_id, int bwp_start = ul_bwp->BWPStart; int bwp_size = ul_bwp->BWPSize; - NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0]; - LOG_D(NR_MAC, "In %s: %4d.%2d Trying to allocate pucch, current DAI %d\n", __FUNCTION__, frame, slot, pucch->dai_c); - - pucch->r_pucch=r_pucch; - AssertFatal(pucch->csi_bits == 0, - "%s(): csi_bits %d in sched_pucch[0]\n", - __func__, - pucch->csi_bits); - - /* if the currently allocated PUCCH of this UE is full, allocate it */ - NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[1]; - if (pucch->dai_c == 2) { - /* advance the UL slot information in PUCCH by one so we won't schedule in - * the same slot again */ - const int f = pucch->frame; - const int s = pucch->ul_slot; - LOG_D(NR_MAC, "In %s: %4d.%2d DAI = 2 pucch currently in %4d.%2d, advancing by 1 slot\n", __FUNCTION__, frame, slot, f, s); - - if (!(csi_pucch - && csi_pucch->csi_bits > 0 - && csi_pucch->frame == f - && csi_pucch->ul_slot == s)) - nr_fill_nfapi_pucch(RC.nrmac[mod_id], frame, slot, pucch, UE); - - memset(pucch, 0, sizeof(*pucch)); - pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; - if(((s + 1)%nr_slots_period) == 0) - pucch->ul_slot = (s + 1 + first_ul_slot_period) % n_slots_frame; - else - pucch->ul_slot = (s + 1) % n_slots_frame; - // we assume that only two indices over the array sched_pucch exist - // skip the CSI PUCCH if it is present and if in the next frame/slot - // and if we don't multiplex - csi_pucch->r_pucch=-1; - if (csi_pucch - && csi_pucch->csi_bits > 0 - && csi_pucch->frame == pucch->frame - && csi_pucch->ul_slot == pucch->ul_slot - && !csi_pucch->simultaneous_harqcsi) { - LOG_D(NR_MAC,"Cannot multiplex csi_pucch for %d.%d\n",csi_pucch->frame,csi_pucch->ul_slot); - nr_fill_nfapi_pucch(RC.nrmac[mod_id], frame, slot, csi_pucch, UE); - - memset(csi_pucch, 0, sizeof(*csi_pucch)); - pucch->frame = pucch->ul_slot == n_slots_frame - 1 ? (pucch->frame + 1) % 1024 : pucch->frame; - if(((pucch->ul_slot + 1)%nr_slots_period) == 0) - pucch->ul_slot = (pucch->ul_slot + 1 + first_ul_slot_period) % n_slots_frame; - else - pucch->ul_slot = (pucch->ul_slot + 1) % n_slots_frame; - } - } - - LOG_D(NR_MAC, "In %s: pucch_acknak 1. DL %4d.%2d, UL_ACK %4d.%2d, DAI_C %d\n", __FUNCTION__, frame, slot, pucch->frame, pucch->ul_slot, pucch->dai_c); - nr_dci_format_t dci_format = NR_DL_DCI_FORMAT_1_0; if(is_common == 0) dci_format = UE->current_DL_BWP.dci_format; uint8_t pdsch_to_harq_feedback[8]; - int max_fb_time = 0; - get_pdsch_to_harq_feedback(pucch_Config, dci_format, &max_fb_time, pdsch_to_harq_feedback); + get_pdsch_to_harq_feedback(pucch_Config, dci_format, pdsch_to_harq_feedback); - LOG_D(NR_MAC, "In %s: 1b. DL %4d.%2d, UL_ACK %4d.%2d, DAI_C %d\n", __FUNCTION__, frame,slot,pucch->frame,pucch->ul_slot,pucch->dai_c); - /* there is a HARQ. Check whether we can use it for this ACKNACK */ - if (pucch->dai_c > 0) { - /* this UE already has a PUCCH occasion */ - // Find the right timing_indicator value. - int i = 0; - while (i < 8) { - int diff = pucch->ul_slot - slot; - if (diff<0) - diff += n_slots_frame; - if (pdsch_to_harq_feedback[i] == diff && - pdsch_to_harq_feedback[i] >= minfbtime) - break; - ++i; - } - if (i >= 8) { - // we cannot reach this timing anymore, allocate and try again - const int f = pucch->frame; - const int s = pucch->ul_slot; - LOG_D(NR_MAC, "In %s: %4d.%2d DAI > 0, cannot reach timing for pucch in %4d.%2d, advancing slot by 1 and trying again\n", __FUNCTION__, frame, slot, f, s); - if (!(csi_pucch && - csi_pucch->csi_bits > 0 && - csi_pucch->frame == f && - csi_pucch->ul_slot == s)) - nr_fill_nfapi_pucch(RC.nrmac[mod_id], frame, slot, pucch, UE); - memset(pucch, 0, sizeof(*pucch)); - pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; - if(((s + 1)%nr_slots_period) == 0) - pucch->ul_slot = (s + 1 + first_ul_slot_period) % n_slots_frame; - else - pucch->ul_slot = (s + 1) % n_slots_frame; - return nr_acknack_scheduling(mod_id, UE, frame, slot, r_pucch,is_common); - } + for (int f=0; f<8; f++) { + // can't schedule ACKNACK before minimum feedback time + if(pdsch_to_harq_feedback[f] < minfbtime) + continue; + const int pucch_slot = (slot + pdsch_to_harq_feedback[f]) % n_slots_frame; + // check if the slot is UL + if(pucch_slot%nr_slots_period < first_ul_slot_period) + continue; + const int pucch_frame = frame + ((slot + pdsch_to_harq_feedback[f]) / n_slots_frame); + int inactive_pucch = -1; + NR_sched_pucch_t *curr_pucch = NULL; + for (int i=0; isched_pucch_size; i++) { + curr_pucch = &sched_ctrl->sched_pucch[i]; + // if there is already an active pucch for this frame and slot + if (curr_pucch->active && + curr_pucch->frame == pucch_frame && + curr_pucch->ul_slot == pucch_slot) { + LOG_D(NR_MAC, "In %s: pucch_acknak DL %4d.%2d, UL_ACK %4d.%2d Bits already in current PUCCH: DAI_C %d CSI %d\n", + __FUNCTION__, frame, slot, pucch_frame, pucch_slot, curr_pucch->dai_c, curr_pucch->csi_bits); + // we can't schedule if short pucch is already full + if (curr_pucch->csi_bits == 0 && + curr_pucch->dai_c == 2) + continue; + // if there is CSI but simultaneous HARQ+CSI is disable we can't schedule + if(!curr_pucch->simultaneous_harqcsi && + curr_pucch->csi_bits>0) + continue; + // TODO we can't schedule more than 11 bits in PUCCH2 for now + if (curr_pucch->csi_bits + curr_pucch->dai_c >= 10) + continue; - pucch->timing_indicator = i; - pucch->dai_c++; - // if there is CSI in this slot update the HARQ information for that one too - if (csi_pucch && - csi_pucch->csi_bits > 0 && - csi_pucch->frame == pucch->frame && - csi_pucch->ul_slot == pucch->ul_slot) { - csi_pucch->timing_indicator = i; - csi_pucch->dai_c++; - } - // retain old resource indicator, and we are good - LOG_D(NR_MAC, "In %s: %4d.%2d. DAI > 0, pucch allocated for %4d.%2d (index %d)\n", __FUNCTION__, frame,slot,pucch->frame,pucch->ul_slot,pucch->timing_indicator); - return 0; - } - - LOG_D(NR_MAC, "In %s: %4d.%2d DAI = 0, looking for new pucch occasion\n", __FUNCTION__, frame, slot); - /* we need to find a new PUCCH occasion */ - - /*(Re)Inizialization of timing information*/ - if ((pucch->frame == 0 && pucch->ul_slot == 0) || - ((pucch->frame*n_slots_frame + pucch->ul_slot) < - (frame*n_slots_frame + slot))) { - AssertFatal(pucch->sr_flag + pucch->dai_c == 0, - "expected no SR/AckNack for UE %04x in %4d.%2d, but has %d/%d for %4d.%2d\n", - UE->rnti, frame, slot, pucch->sr_flag, pucch->dai_c, pucch->frame, pucch->ul_slot); - const int s = next_ul_slot; - pucch->frame = s < n_slots_frame ? frame : (frame + 1) % 1024; - pucch->ul_slot = s % n_slots_frame; - } - - // Find the right timing_indicator value. - int ind_found = -1; - // while we are within the feedback limits - uint16_t *vrb_map_UL; - while ((n_slots_frame + pucch->ul_slot - slot) % n_slots_frame <= max_fb_time) { - // checking if in ul_slot the resources potentially to be assigned to this PUCCH are available - vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch->ul_slot * MAX_BWP_SIZE]; - bool ret = test_acknack_vrb_occupation(sched_ctrl, - pucch, - vrb_map_UL, - scc, - pucch_Config, - r_pucch, - bwp_start, - bwp_size); - if (ret) { - int i = 0; - while (i < 8) { - LOG_D(NR_MAC,"pdsch_to_harq_feedback[%d] = %d (pucch->ul_slot %d - slot %d)\n", - i,pdsch_to_harq_feedback[i],pucch->ul_slot,slot); - int diff = pucch->ul_slot - slot; - if (diff<0) - diff += n_slots_frame; - if (pdsch_to_harq_feedback[i] == diff && - pdsch_to_harq_feedback[i] >= minfbtime) { - ind_found = i; - break; - } - ++i; + // otherwise we can schedule in this active PUCCH + // no need to check VRB occupation because already done when PUCCH has been activated + curr_pucch->timing_indicator = f; + curr_pucch->dai_c++; + LOG_D(NR_MAC, "In %s: DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d CSI %d\n", + __FUNCTION__,frame,slot,curr_pucch->frame,curr_pucch->ul_slot,i,f,curr_pucch->dai_c,curr_pucch->csi_bits); + return i; // index of current PUCCH structure } - if (ind_found!=-1) - break; + else if (!curr_pucch->active) + inactive_pucch = i; } - // advance to the next ul slot - const int f = pucch->frame; - const int s = pucch->ul_slot; - pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; - if(((s + 1)%nr_slots_period) == 0) - pucch->ul_slot = (s + 1 + first_ul_slot_period) % n_slots_frame; - else - pucch->ul_slot = (s + 1) % n_slots_frame; - } - if (ind_found==-1) { - LOG_D(NR_MAC, - "%4d.%2d could not find pdsch_to_harq_feedback for UE %04x: earliest " - "ack slot %d\n", - frame, - slot, - UE->rnti, - pucch->ul_slot); - return -1; - } + if (inactive_pucch>0) { + curr_pucch = &sched_ctrl->sched_pucch[inactive_pucch]; + // checking if in ul_slot the resources potentially to be assigned to this PUCCH are available + uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch_slot * MAX_BWP_SIZE]; + bool ret = test_pucch0_vrb_occupation(sched_ctrl, + curr_pucch, + vrb_map_UL, + scc, + pucch_Config, + r_pucch, + bwp_start, + bwp_size); + if(!ret) { + LOG_D(NR_MAC, "In %s: DL %4d.%2d, UL_ACK %4d.%2d PRB resources for this occasion are already occupied, move to the following occasion\n", + __FUNCTION__,frame,slot,curr_pucch->frame,curr_pucch->ul_slot); + continue; + } + // allocating a new PUCCH structure for this occasion + curr_pucch->active = true; + curr_pucch->frame = pucch_frame; + curr_pucch->ul_slot = pucch_slot; + curr_pucch->timing_indicator = f; // index in the list of timing indicators + curr_pucch->dai_c++; + curr_pucch->resource_indicator = 0; // each UE has dedicated PUCCH resources + curr_pucch->r_pucch=r_pucch; - if (csi_pucch && - csi_pucch->csi_bits > 0 && - csi_pucch->frame == pucch->frame && - csi_pucch->ul_slot == pucch->ul_slot) { - // skip the CSI PUCCH if it is present and if in the next frame/slot - // and if we don't multiplex - /* FIXME currently we support at most 11 bits in pucch2 so skip also in that case. - We need to set the limit to 10 because SR scheduling has been moved afterwards */ - if(!csi_pucch->simultaneous_harqcsi - || ((csi_pucch->csi_bits + csi_pucch->dai_c) >= 10)) { - LOG_D(NR_MAC,"Cannot multiplex csi_pucch %d +csi_pucch->dai_c %d for %d.%d\n",csi_pucch->csi_bits,csi_pucch->dai_c,csi_pucch->frame,csi_pucch->ul_slot); - nr_fill_nfapi_pucch(RC.nrmac[mod_id], frame, slot, csi_pucch, UE); - memset(csi_pucch, 0, sizeof(*csi_pucch)); - /* advance the UL slot information in PUCCH by one so we won't schedule in - * the same slot again */ - const int f = pucch->frame; - const int s = pucch->ul_slot; - memset(pucch, 0, sizeof(*pucch)); - pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; - if(((s + 1)%nr_slots_period) == 0) - pucch->ul_slot = (s + 1 + first_ul_slot_period) % n_slots_frame; - else - pucch->ul_slot = (s + 1) % n_slots_frame; - return nr_acknack_scheduling(mod_id, UE, frame, slot, r_pucch,is_common); - } - // multiplexing harq and csi in a pucch - else { - csi_pucch->timing_indicator = ind_found; - csi_pucch->dai_c++; - memset(pucch,0,sizeof(*pucch)); + LOG_D(NR_MAC, "In %s: DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d\n", + __FUNCTION__,frame,slot,curr_pucch->frame,curr_pucch->ul_slot,inactive_pucch,f,curr_pucch->dai_c); - LOG_D(NR_MAC,"multiplexing csi_pucch %d +csi_pucch->dai_c %d for %d.%d\n",csi_pucch->csi_bits,csi_pucch->dai_c,csi_pucch->frame,csi_pucch->ul_slot); - return 1; + // blocking resources for current PUCCH in VRB map + for (int l=0; lnr_of_symb; l++) { + uint16_t symb = SL_to_bitmap(curr_pucch->start_symb+l, 1); + int prb; + if (l==1 && curr_pucch->second_hop_prb != 0) + prb = curr_pucch->second_hop_prb; + else + prb = curr_pucch->prb_start; + vrb_map_UL[bwp_start+prb] |= symb; + } + + return inactive_pucch; // index of current PUCCH structure } } - - pucch->timing_indicator = ind_found; // index in the list of timing indicators - - LOG_D(NR_MAC, "In %s: 2. DAI 0 DL %4d.%2d, UL_ACK %4d.%2d (index %d)\n", __FUNCTION__, frame,slot,pucch->frame,pucch->ul_slot,pucch->timing_indicator); - - pucch->dai_c++; - pucch->resource_indicator = 0; // each UE has dedicated PUCCH resources - pucch->r_pucch=r_pucch; - - vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch->ul_slot * MAX_BWP_SIZE]; - for (int l=0; lnr_of_symb; l++) { - uint16_t symb = SL_to_bitmap(pucch->start_symb+l, 1); - int prb; - if (l==1 && pucch->second_hop_prb != 0) - prb = pucch->second_hop_prb; - else - prb = pucch->prb_start; - vrb_map_UL[bwp_start+prb] |= symb; - } - return 0; + LOG_D(NR_MAC, "In %s: DL %4d.%2d, Couldn't find scheduling occasion for this HARQ process\n", + __FUNCTION__, frame, slot); + return -1; } -void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) +void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot, int mod_id) { if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slot / 64], slot)) return; - + int CC_id = 0; + const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; UE_iterator(nrmac->UE_info.list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; @@ -1349,95 +1205,64 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) LOG_D(NR_MAC, "%4d.%2d Scheduling Request identified\n", SFN, slot); NR_PUCCH_ResourceId_t *PucchResourceId = SchedulingRequestResourceConfig->resource; - int found = -1; + int idx = -1; NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0]; // set with formats 0,1 int n_list = pucchresset->resourceList.list.count; for (int i=0; iresourceList.list.array[i] == *PucchResourceId ) - found = i; + idx = i; } - AssertFatal(found>-1,"SR resource not found among PUCCH resources"); + AssertFatal(idx>-1,"SR resource not found among PUCCH resources"); - /* loop through nFAPI PUCCH messages: if the UEs is in there in this slot - * with the resource_indicator, it means we already allocated that PUCCH - * resource for AckNack (e.g., the UE has been scheduled often), and we - * just need to add the SR_flag. Otherwise, just allocate in the internal - * PUCCH resource, and nr_schedule_pucch() will handle the rest */ - NR_PUCCH_Resource_t *pucch_res = pucch_Config->resourceToAddModList->list.array[found]; - /* for the moment, can only handle SR on PUCCH Format 0 */ - DevAssert(pucch_res->format.present == NR_PUCCH_Resource__format_PR_format0); - nfapi_nr_ul_tti_request_t *ul_tti_req = &nrmac->UL_tti_req_ahead[0][slot]; - bool nfapi_allocated = false; - for (int i = 0; i < ul_tti_req->n_pdus; ++i) { - if (ul_tti_req->pdus_list[i].pdu_type != NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE) - continue; - nfapi_nr_pucch_pdu_t *pdu = &ul_tti_req->pdus_list[i].pucch_pdu; - /* check that it is our PUCCH F0. Assuming there can be only one */ - if (pdu->rnti == UE->rnti - && pdu->format_type == 0 // does not use NR_PUCCH_Resource__format_PR_format0 - && pdu->initial_cyclic_shift == pucch_res->format.choice.format0->initialCyclicShift - && pdu->nr_of_symbols == pucch_res->format.choice.format0->nrofSymbols - && pdu->start_symbol_index == pucch_res->format.choice.format0->startingSymbolIndex) { - LOG_D(NR_MAC,"%4d.%2d adding SR_flag 1 to PUCCH format 0 nFAPI SR for RNTI %04x\n", SFN, slot, pdu->rnti); - pdu->sr_flag = 1; - nfapi_allocated = true; - break; - } else if (pdu->rnti == UE->rnti - && pdu->format_type == 2 // does not use NR_PUCCH_Resource__format_PR_format0 - && pdu->nr_of_symbols == pucch_res->format.choice.format2->nrofSymbols - && pdu->start_symbol_index == pucch_res->format.choice.format2->startingSymbolIndex) { - LOG_D(NR_MAC,"%4d.%2d adding SR_flag 1 to PUCCH format 2 nFAPI SR for RNTI %04x\n", SFN, slot, pdu->rnti); - pdu->sr_flag = 1; - nfapi_allocated = true; - break; - } else if (pdu->rnti == UE->rnti - && pdu->format_type == 1 // does not use NR_PUCCH_Resource__format_PR_format0 - && pdu->nr_of_symbols == pucch_res->format.choice.format1->nrofSymbols - && pdu->start_symbol_index == pucch_res->format.choice.format1->startingSymbolIndex) { - LOG_D(NR_MAC,"%4d.%2d adding SR_flag 1 to PUCCH format 1 nFAPI SR for RNTI %04x\n", SFN, slot, pdu->rnti); - pdu->sr_flag = 1; - nfapi_allocated = true; - break; - } else if (pdu->rnti == UE->rnti - && pdu->format_type == 3 // does not use NR_PUCCH_Resource__format_PR_format0 - && pdu->nr_of_symbols == pucch_res->format.choice.format3->nrofSymbols - && pdu->start_symbol_index == pucch_res->format.choice.format3->startingSymbolIndex) { - LOG_D(NR_MAC,"%4d.%2d adding SR_flag 1 to PUCCH format 3 nFAPI SR for RNTI %04x\n", SFN, slot, pdu->rnti); - pdu->sr_flag = 1; - nfapi_allocated = true; - break; - } else if (pdu->rnti == UE->rnti - && pdu->format_type == 4 // does not use NR_PUCCH_Resource__format_PR_format0 - && pdu->nr_of_symbols == pucch_res->format.choice.format4->nrofSymbols - && pdu->start_symbol_index == pucch_res->format.choice.format4->startingSymbolIndex) { - LOG_D(NR_MAC,"%4d.%2d adding SR_flag 1 to PUCCH format 4 nFAPI SR for RNTI %04x\n", SFN, slot, pdu->rnti); - pdu->sr_flag = 1; - nfapi_allocated = true; + NR_sched_pucch_t *curr_pucch = NULL; + bool found = false; + int free_pucch = -1; + for (int i=0; isched_pucch_size; i++) { + curr_pucch = &sched_ctrl->sched_pucch[i]; + if (curr_pucch->active && + curr_pucch->frame == SFN && + curr_pucch->ul_slot == slot && + curr_pucch->resource_indicator == found) { + curr_pucch->sr_flag = true; + found = true; break; } + else if (!curr_pucch->active) + free_pucch = i; // found an available pucch structure } - - if (nfapi_allocated) // break scheduling resource loop, continue next UE - break; - - /* we did not find it: check if current PUCCH is for the current slot, in - * which case we add the SR to it; otherwise, allocate SR separately */ - NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[0]; - if (curr_pucch->frame == SFN && curr_pucch->ul_slot == slot) { - if (curr_pucch->resource_indicator != found) { - LOG_W(NR_MAC, "%4d.%2d expected PUCCH in this slot to have resource indicator of SR (%d), skipping SR\n", SFN, slot, found); + AssertFatal(found || free_pucch>0, "Coulnd't find an available PUCCH resource to schedule SR\n"); + if (!found) { + uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[slot * MAX_BWP_SIZE]; + int bwp_start = ul_bwp->BWPStart; + int bwp_size = ul_bwp->BWPSize; + NR_sched_pucch_t *sched_sr = &sched_ctrl->sched_pucch[free_pucch]; + bool ret = test_pucch0_vrb_occupation(sched_ctrl, + sched_sr, + vrb_map_UL, + scc, + pucch_Config, + -1, + bwp_start, + bwp_size); + if (!ret) { + LOG_E(NR_MAC,"Cannot schedule SR. PRBs not available\n"); continue; } - curr_pucch->sr_flag = true; - } else { - NR_sched_pucch_t sched_sr = { - .frame = SFN, - .ul_slot = slot, - .sr_flag = true, - .resource_indicator = found, - .r_pucch = -1 - }; - nr_fill_nfapi_pucch(nrmac, SFN, slot, &sched_sr, UE); + sched_sr->frame = SFN; + sched_sr->ul_slot = slot; + sched_sr->sr_flag = true; + sched_sr->resource_indicator = idx; + sched_sr->r_pucch = -1; + sched_sr->active = true; + for (int l=0; lnr_of_symb; l++) { + uint16_t symb = SL_to_bitmap(sched_sr->start_symb+l, 1); + int prb; + if (l==1 && sched_sr->second_hop_prb != 0) + prb = sched_sr->second_hop_prb; + else + prb = sched_sr->prb_start; + vrb_map_UL[bwp_start+prb] |= symb; + } } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 4497e89030..c7c44f95d7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -218,7 +218,6 @@ int nr_acknack_scheduling(int Mod_idP, void get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config, nr_dci_format_t dci_format, - int *max_fb_time, uint8_t *pdsch_to_harq_feedback); void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu, @@ -466,6 +465,10 @@ uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx); uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format); +void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, + NR_UE_UL_BWP_t *ul_bwp, + NR_ServingCellConfigCommon_t *scc); + const int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot); const int get_ul_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot); @@ -490,7 +493,7 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options, void UL_tti_req_ahead_initialization(gNB_MAC_INST * gNB, NR_ServingCellConfigCommon_t *scc, int n, int CCid); -void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP); +void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP, int mod_id); size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 4d65de8403..a74dafa29c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -123,6 +123,7 @@ typedef struct NR_UE_UL_BWP { uint8_t transform_precoding; uint8_t mcs_table; nr_dci_format_t dci_format; + int max_fb_time; } NR_UE_UL_BWP_t; typedef enum { @@ -354,6 +355,7 @@ typedef struct UE_info { } NR_UE_mac_ce_ctrl_t; typedef struct NR_sched_pucch { + bool active; int frame; int ul_slot; bool sr_flag; @@ -560,9 +562,11 @@ typedef struct { /// corresponding to the sched_pusch/sched_pdsch structures below int cce_index; uint8_t aggregation_level; + /// PUCCH scheduling information. Array of two: HARQ+SR in the first field, /// CSI in second. This order is important for nr_acknack_scheduling()! - NR_sched_pucch_t sched_pucch[2]; + NR_sched_pucch_t *sched_pucch; + int sched_pucch_size; /// Sched PUSCH: scheduling decisions, copied into HARQ and cleared every TTI NR_sched_pusch_t sched_pusch; From ef701be83df59e91952c903aeda2b26ba73a783d Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 25 Aug 2022 18:51:28 +0200 Subject: [PATCH 2/5] bugfixes for SR --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 1 + openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 66f431946d..14214b75d6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1166,6 +1166,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, break; case NR_PUCCH_Resource__format_PR_format2 : pucch_pdu->format_type = 2; + pucch_pdu->sr_flag = O_sr; pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols; pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex; pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 2c4166f261..4d692baad6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1222,7 +1222,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot, int mod if (curr_pucch->active && curr_pucch->frame == SFN && curr_pucch->ul_slot == slot && - curr_pucch->resource_indicator == found) { + curr_pucch->resource_indicator == idx) { curr_pucch->sr_flag = true; found = true; break; @@ -1230,7 +1230,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot, int mod else if (!curr_pucch->active) free_pucch = i; // found an available pucch structure } - AssertFatal(found || free_pucch>0, "Coulnd't find an available PUCCH resource to schedule SR\n"); + AssertFatal(found || free_pucch>-1, "Coulnd't find an available PUCCH resource to schedule SR\n"); if (!found) { uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[slot * MAX_BWP_SIZE]; int bwp_start = ul_bwp->BWPStart; From 8c5cf09826eb38bce000a613e25c0565d979d477 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 29 Sep 2022 16:54:33 +0200 Subject: [PATCH 3/5] addressing review --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 27 +++++++++---------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 4 +-- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index ac9b86e5c9..84f90d48ae 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -236,7 +236,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, nr_schedule_ue_spec(module_idP, frame, slot); stop_meas(&gNB->schedule_dlsch); - nr_sr_reporting(RC.nrmac[module_idP], frame, slot, module_idP); + nr_sr_reporting(RC.nrmac[module_idP], frame, slot); nr_schedule_pucch(RC.nrmac[module_idP], frame, slot); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 4d692baad6..6ece1ef4f1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1099,8 +1099,8 @@ int nr_acknack_scheduling(int mod_id, if (curr_pucch->active && curr_pucch->frame == pucch_frame && curr_pucch->ul_slot == pucch_slot) { - LOG_D(NR_MAC, "In %s: pucch_acknak DL %4d.%2d, UL_ACK %4d.%2d Bits already in current PUCCH: DAI_C %d CSI %d\n", - __FUNCTION__, frame, slot, pucch_frame, pucch_slot, curr_pucch->dai_c, curr_pucch->csi_bits); + LOG_D(NR_MAC, "pucch_acknak DL %4d.%2d, UL_ACK %4d.%2d Bits already in current PUCCH: DAI_C %d CSI %d\n", + frame, slot, pucch_frame, pucch_slot, curr_pucch->dai_c, curr_pucch->csi_bits); // we can't schedule if short pucch is already full if (curr_pucch->csi_bits == 0 && curr_pucch->dai_c == 2) @@ -1117,8 +1117,8 @@ int nr_acknack_scheduling(int mod_id, // no need to check VRB occupation because already done when PUCCH has been activated curr_pucch->timing_indicator = f; curr_pucch->dai_c++; - LOG_D(NR_MAC, "In %s: DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d CSI %d\n", - __FUNCTION__,frame,slot,curr_pucch->frame,curr_pucch->ul_slot,i,f,curr_pucch->dai_c,curr_pucch->csi_bits); + LOG_D(NR_MAC, "DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d CSI %d\n", + frame,slot,curr_pucch->frame,curr_pucch->ul_slot,i,f,curr_pucch->dai_c,curr_pucch->csi_bits); return i; // index of current PUCCH structure } else if (!curr_pucch->active) @@ -1137,8 +1137,8 @@ int nr_acknack_scheduling(int mod_id, bwp_start, bwp_size); if(!ret) { - LOG_D(NR_MAC, "In %s: DL %4d.%2d, UL_ACK %4d.%2d PRB resources for this occasion are already occupied, move to the following occasion\n", - __FUNCTION__,frame,slot,curr_pucch->frame,curr_pucch->ul_slot); + LOG_D(NR_MAC, "DL %4d.%2d, UL_ACK %4d.%2d PRB resources for this occasion are already occupied, move to the following occasion\n", + frame,slot,curr_pucch->frame,curr_pucch->ul_slot); continue; } // allocating a new PUCCH structure for this occasion @@ -1150,30 +1150,27 @@ int nr_acknack_scheduling(int mod_id, curr_pucch->resource_indicator = 0; // each UE has dedicated PUCCH resources curr_pucch->r_pucch=r_pucch; - LOG_D(NR_MAC, "In %s: DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d\n", - __FUNCTION__,frame,slot,curr_pucch->frame,curr_pucch->ul_slot,inactive_pucch,f,curr_pucch->dai_c); + LOG_D(NR_MAC, "DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d\n", + frame,slot,curr_pucch->frame,curr_pucch->ul_slot,inactive_pucch,f,curr_pucch->dai_c); // blocking resources for current PUCCH in VRB map for (int l=0; lnr_of_symb; l++) { uint16_t symb = SL_to_bitmap(curr_pucch->start_symb+l, 1); - int prb; + int prb = curr_pucch->prb_start; if (l==1 && curr_pucch->second_hop_prb != 0) prb = curr_pucch->second_hop_prb; - else - prb = curr_pucch->prb_start; vrb_map_UL[bwp_start+prb] |= symb; } return inactive_pucch; // index of current PUCCH structure } } - LOG_D(NR_MAC, "In %s: DL %4d.%2d, Couldn't find scheduling occasion for this HARQ process\n", - __FUNCTION__, frame, slot); + LOG_D(NR_MAC, "DL %4d.%2d, Couldn't find scheduling occasion for this HARQ process\n", frame, slot); return -1; } -void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot, int mod_id) +void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) { if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slot / 64], slot)) return; @@ -1232,7 +1229,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot, int mod } AssertFatal(found || free_pucch>-1, "Coulnd't find an available PUCCH resource to schedule SR\n"); if (!found) { - uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[slot * MAX_BWP_SIZE]; + uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[slot * MAX_BWP_SIZE]; int bwp_start = ul_bwp->BWPStart; int bwp_size = ul_bwp->BWPSize; NR_sched_pucch_t *sched_sr = &sched_ctrl->sched_pucch[free_pucch]; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index c7c44f95d7..2e3ccf4ba6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -493,7 +493,7 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options, void UL_tti_req_ahead_initialization(gNB_MAC_INST * gNB, NR_ServingCellConfigCommon_t *scc, int n, int CCid); -void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP, int mod_id); +void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP); size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index a74dafa29c..17f0504e15 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -563,8 +563,8 @@ typedef struct { int cce_index; uint8_t aggregation_level; - /// PUCCH scheduling information. Array of two: HARQ+SR in the first field, - /// CSI in second. This order is important for nr_acknack_scheduling()! + /// Array of PUCCH scheduling information. + /// Its size depends on TDD configuration and max feedback time NR_sched_pucch_t *sched_pucch; int sched_pucch_size; From 0df6dfba94285d4015ce492e8bf317386e5d4612 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 11 Oct 2022 15:10:32 +0200 Subject: [PATCH 4/5] fixing the new PUCCH procedures --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 25 ++- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 155 +++++++++--------- 2 files changed, 87 insertions(+), 93 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 14214b75d6..36ba747e72 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2376,18 +2376,6 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, else UL_BWP->pucch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup; - UL_BWP->max_fb_time = 0; - if(DL_BWP->dci_format != NR_DL_DCI_FORMAT_1_0 && - UL_BWP->pucch_Config) { - for (int i=0; ipucch_Config->dl_DataToUL_ACK->list.count; i++) { - if(*UL_BWP->pucch_Config->dl_DataToUL_ACK->list.array[i] > UL_BWP->max_fb_time) - UL_BWP->max_fb_time = *UL_BWP->pucch_Config->dl_DataToUL_ACK->list.array[i]; - } - } - else - UL_BWP->max_fb_time = 8; // default value - - if(UE) { // setting PDCCH related structures for sched_ctrl sched_ctrl->search_space = get_searchspace(scc, @@ -2422,8 +2410,18 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, if (UL_BWP->csi_MeasConfig) compute_csi_bitlen (UL_BWP->csi_MeasConfig, UE->csi_report_template); - set_sched_pucch_list(sched_ctrl, UL_BWP, scc); + UL_BWP->max_fb_time = 0; + if(DL_BWP->dci_format != NR_DL_DCI_FORMAT_1_0 && + UL_BWP->pucch_Config) { + for (int i=0; ipucch_Config->dl_DataToUL_ACK->list.count; i++) { + if(*UL_BWP->pucch_Config->dl_DataToUL_ACK->list.array[i] > UL_BWP->max_fb_time) + UL_BWP->max_fb_time = *UL_BWP->pucch_Config->dl_DataToUL_ACK->list.array[i]; + } + } + else + UL_BWP->max_fb_time = 8; // default value + set_sched_pucch_list(sched_ctrl, UL_BWP, scc); } if(ra) { @@ -2576,7 +2574,6 @@ void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs]; const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; - const int list_size = n_ul_slots_period << (ul_bwp->max_fb_time/nr_slots_period); if(!sched_ctrl->sched_pucch) { sched_ctrl->sched_pucch = malloc(list_size * sizeof(*sched_ctrl->sched_pucch)); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 6ece1ef4f1..f718c6703c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -70,7 +70,7 @@ static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac, LOG_D(NR_MAC, "%s %4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, DAI %d, CSI %d on res %d\n", - pucch->dai_c>0 ? "pucch_acknak" : "", + pucch->dai_c>0 ? "pucch_acknack" : "", frame, slot, pucch->frame, @@ -204,17 +204,15 @@ void nr_csi_meas_reporting(int Mod_idP, AssertFatal(res_index < n, "CSI pucch resource %ld not found among PUCCH resources\n", pucchcsires->pucch_Resource); - // find free PUCCH that is in order with possibly existing PUCCH - // schedulings (other CSI, SR) - NR_sched_pucch_t *curr_pucch = NULL; - for (int i=0; isched_pucch_size; i++) { - curr_pucch = &sched_ctrl->sched_pucch[i]; - if (!curr_pucch->active) - break; // found an available pucch structure - } - AssertFatal(curr_pucch, - "PUCCH structure not found for UE %04x\n", - UE->rnti); + const NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels[0].ServingCellConfigCommon; + const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; + AssertFatal(tdd || RC.nrmac[Mod_idP]->common_channels[0].frame_type == FDD, "Dynamic TDD not handled yet\n"); + const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; + const int first_ul_slot_period = tdd ? tdd->nrofDownlinkSlots : 0; + const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; + const int pucch_index = ((sched_slot % nr_slots_period) - first_ul_slot_period + (sched_slot / nr_slots_period) * n_ul_slots_period) % sched_ctrl->sched_pucch_size; + NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index]; + AssertFatal(curr_pucch->active == false, "CSI structure is scheduled in advance. It should be free!\n"); curr_pucch->r_pucch = -1; curr_pucch->frame = sched_frame; curr_pucch->ul_slot = sched_slot; @@ -1062,6 +1060,7 @@ int nr_acknack_scheduling(int mod_id, AssertFatal(tdd || RC.nrmac[mod_id]->common_channels[CC_id].frame_type == FDD, "Dynamic TDD not handled yet\n"); const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; const int first_ul_slot_period = tdd ? tdd->nrofDownlinkSlots : 0; + const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; /* for the moment, we consider: * * only pucch_sched[0] holds HARQ (and SR) @@ -1090,42 +1089,40 @@ int nr_acknack_scheduling(int mod_id, // check if the slot is UL if(pucch_slot%nr_slots_period < first_ul_slot_period) continue; - const int pucch_frame = frame + ((slot + pdsch_to_harq_feedback[f]) / n_slots_frame); - int inactive_pucch = -1; - NR_sched_pucch_t *curr_pucch = NULL; - for (int i=0; isched_pucch_size; i++) { - curr_pucch = &sched_ctrl->sched_pucch[i]; - // if there is already an active pucch for this frame and slot - if (curr_pucch->active && - curr_pucch->frame == pucch_frame && - curr_pucch->ul_slot == pucch_slot) { - LOG_D(NR_MAC, "pucch_acknak DL %4d.%2d, UL_ACK %4d.%2d Bits already in current PUCCH: DAI_C %d CSI %d\n", - frame, slot, pucch_frame, pucch_slot, curr_pucch->dai_c, curr_pucch->csi_bits); - // we can't schedule if short pucch is already full - if (curr_pucch->csi_bits == 0 && - curr_pucch->dai_c == 2) - continue; - // if there is CSI but simultaneous HARQ+CSI is disable we can't schedule - if(!curr_pucch->simultaneous_harqcsi && - curr_pucch->csi_bits>0) - continue; - // TODO we can't schedule more than 11 bits in PUCCH2 for now - if (curr_pucch->csi_bits + curr_pucch->dai_c >= 10) - continue; + const int pucch_frame = (frame + ((slot + pdsch_to_harq_feedback[f]) / n_slots_frame)) & 1023; + const int pucch_index = ((pucch_slot % nr_slots_period) - first_ul_slot_period + (pucch_slot / nr_slots_period) * n_ul_slots_period) % sched_ctrl->sched_pucch_size; + NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index]; + if (curr_pucch->active && + curr_pucch->frame == pucch_frame && + curr_pucch->ul_slot == pucch_slot) { // if there is already a PUCCH in given frame and slot + LOG_D(NR_MAC, "pucch_acknack DL %4d.%2d, UL_ACK %4d.%2d Bits already in current PUCCH: DAI_C %d CSI %d\n", + frame, slot, pucch_frame, pucch_slot, curr_pucch->dai_c, curr_pucch->csi_bits); + // we can't schedule if short pucch is already full + if (curr_pucch->csi_bits == 0 && + curr_pucch->dai_c == 2) + continue; + // if there is CSI but simultaneous HARQ+CSI is disable we can't schedule + if(!curr_pucch->simultaneous_harqcsi && + curr_pucch->csi_bits>0) + continue; + // TODO we can't schedule more than 11 bits in PUCCH2 for now + if (curr_pucch->csi_bits + curr_pucch->dai_c >= 10) + continue; - // otherwise we can schedule in this active PUCCH - // no need to check VRB occupation because already done when PUCCH has been activated - curr_pucch->timing_indicator = f; - curr_pucch->dai_c++; - LOG_D(NR_MAC, "DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d CSI %d\n", - frame,slot,curr_pucch->frame,curr_pucch->ul_slot,i,f,curr_pucch->dai_c,curr_pucch->csi_bits); - return i; // index of current PUCCH structure - } - else if (!curr_pucch->active) - inactive_pucch = i; + // otherwise we can schedule in this active PUCCH + // no need to check VRB occupation because already done when PUCCH has been activated + curr_pucch->timing_indicator = f; + curr_pucch->dai_c++; + LOG_D(NR_MAC, "DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d CSI %d\n", + frame,slot,curr_pucch->frame,curr_pucch->ul_slot,pucch_index,f,curr_pucch->dai_c,curr_pucch->csi_bits); + return pucch_index; // index of current PUCCH structure } - if (inactive_pucch>0) { - curr_pucch = &sched_ctrl->sched_pucch[inactive_pucch]; + else if (curr_pucch->active) { + LOG_E(NR_MAC, "This shouldn't happen! curr_pucch frame.slot %d.%d not matching with computed frame.slot %d.%d\n", + curr_pucch->frame, curr_pucch->ul_slot, pucch_frame, pucch_slot); + continue; + } + else { // unoccupied occasion // checking if in ul_slot the resources potentially to be assigned to this PUCCH are available uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch_slot * MAX_BWP_SIZE]; bool ret = test_pucch0_vrb_occupation(sched_ctrl, @@ -1151,7 +1148,7 @@ int nr_acknack_scheduling(int mod_id, curr_pucch->r_pucch=r_pucch; LOG_D(NR_MAC, "DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d\n", - frame,slot,curr_pucch->frame,curr_pucch->ul_slot,inactive_pucch,f,curr_pucch->dai_c); + frame,slot,curr_pucch->frame,curr_pucch->ul_slot,pucch_index,f,curr_pucch->dai_c); // blocking resources for current PUCCH in VRB map for (int l=0; lnr_of_symb; l++) { @@ -1162,7 +1159,7 @@ int nr_acknack_scheduling(int mod_id, vrb_map_UL[bwp_start+prb] |= symb; } - return inactive_pucch; // index of current PUCCH structure + return pucch_index; // index of current PUCCH structure } } LOG_D(NR_MAC, "DL %4d.%2d, Couldn't find scheduling occasion for this HARQ process\n", frame, slot); @@ -1175,7 +1172,6 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slot / 64], slot)) return; int CC_id = 0; - const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; UE_iterator(nrmac->UE_info.list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; @@ -1211,30 +1207,31 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) } AssertFatal(idx>-1,"SR resource not found among PUCCH resources"); - NR_sched_pucch_t *curr_pucch = NULL; - bool found = false; - int free_pucch = -1; - for (int i=0; isched_pucch_size; i++) { - curr_pucch = &sched_ctrl->sched_pucch[i]; - if (curr_pucch->active && - curr_pucch->frame == SFN && - curr_pucch->ul_slot == slot && - curr_pucch->resource_indicator == idx) { - curr_pucch->sr_flag = true; - found = true; - break; - } - else if (!curr_pucch->active) - free_pucch = i; // found an available pucch structure + const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; + const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; + AssertFatal(tdd || nrmac->common_channels[CC_id].frame_type == FDD, "Dynamic TDD not handled yet\n"); + const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; + const int first_ul_slot_period = tdd ? tdd->nrofDownlinkSlots : 0; + const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; + const int pucch_index = ((slot % nr_slots_period) - first_ul_slot_period + (slot / nr_slots_period) * n_ul_slots_period) % sched_ctrl->sched_pucch_size; + NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index]; + + if (curr_pucch->active && + curr_pucch->frame == SFN && + curr_pucch->ul_slot == slot && + curr_pucch->resource_indicator == idx) + curr_pucch->sr_flag = true; + else if (curr_pucch->active) { + LOG_E(NR_MAC, "This shouldn't happen! curr_pucch frame.slot %d.%d not matching with SR function frame.slot %d.%d\n", + curr_pucch->frame, curr_pucch->ul_slot, SFN, slot); + continue; } - AssertFatal(found || free_pucch>-1, "Coulnd't find an available PUCCH resource to schedule SR\n"); - if (!found) { + else { uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[slot * MAX_BWP_SIZE]; int bwp_start = ul_bwp->BWPStart; int bwp_size = ul_bwp->BWPSize; - NR_sched_pucch_t *sched_sr = &sched_ctrl->sched_pucch[free_pucch]; bool ret = test_pucch0_vrb_occupation(sched_ctrl, - sched_sr, + curr_pucch, vrb_map_UL, scc, pucch_Config, @@ -1245,19 +1242,19 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) LOG_E(NR_MAC,"Cannot schedule SR. PRBs not available\n"); continue; } - sched_sr->frame = SFN; - sched_sr->ul_slot = slot; - sched_sr->sr_flag = true; - sched_sr->resource_indicator = idx; - sched_sr->r_pucch = -1; - sched_sr->active = true; - for (int l=0; lnr_of_symb; l++) { - uint16_t symb = SL_to_bitmap(sched_sr->start_symb+l, 1); + curr_pucch->frame = SFN; + curr_pucch->ul_slot = slot; + curr_pucch->sr_flag = true; + curr_pucch->resource_indicator = idx; + curr_pucch->r_pucch = -1; + curr_pucch->active = true; + for (int l=0; lnr_of_symb; l++) { + uint16_t symb = SL_to_bitmap(curr_pucch->start_symb+l, 1); int prb; - if (l==1 && sched_sr->second_hop_prb != 0) - prb = sched_sr->second_hop_prb; + if (l==1 && curr_pucch->second_hop_prb != 0) + prb = curr_pucch->second_hop_prb; else - prb = sched_sr->prb_start; + prb = curr_pucch->prb_start; vrb_map_UL[bwp_start+prb] |= symb; } } From 3247cdd0c3e1f41a815e9d96788a42ec7524cf97 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 27 Oct 2022 09:27:22 +0200 Subject: [PATCH 5/5] addressing review --- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 6 - openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 2 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 4 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 2 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 38 ++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 176 +++++++++--------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 6 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 3 +- 11 files changed, 122 insertions(+), 121 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index dd138e5265..85d9a641fa 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -1536,12 +1536,6 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, corr32_im[symb][group][aa]+((int16_t*)(&prod_im[aa]))[0]); #endif - LOG_D(PHY,"pucch2 cw %d group %d aa %d: (%d,%d)+(%d,%d) = (%d,%d)\n",cw,group,aa, - corr32_re[symb][group][aa],corr32_im[symb][group][aa], - ((int16_t*)(&prod_re[aa]))[0], - ((int16_t*)(&prod_im[aa]))[0], - corr32_re[symb][group][aa]+((int16_t*)(&prod_re[aa]))[0], - corr32_im[symb][group][aa]+((int16_t*)(&prod_im[aa]))[0]); corr_re = ( corr32_re[symb][group][aa]+((int16_t*)(&prod_re[aa]))[0]); corr_im = ( corr32_im[symb][group][aa]+((int16_t*)(&prod_im[aa]))[0]); diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 94bb084f89..253b85cfce 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -4427,7 +4427,7 @@ void fill_searchSpaceZero(NR_SearchSpace_t *ss0, NR_Type0_PDCCH_CSS_config_t *ty } -void find_period_offest_SR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset) { +void find_period_offset_SR(const NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset) { NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR P_O = SchedulingReqRec->periodicityAndOffset->present; switch (P_O){ case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl1: diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 9a8750ae51..e3ad29b43f 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -221,7 +221,7 @@ uint16_t compute_pucch_prb_size(uint8_t format, int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH); -void find_period_offest_SR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset); +void find_period_offset_SR(const NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset); void csi_period_offset(NR_CSI_ReportConfig_t *csirep, struct NR_CSI_ResourcePeriodicityAndOffset *periodicityAndOffset, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 161cdb7079..963a8d4b2f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2388,7 +2388,7 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, NR_SchedulingRequestResourceConfig_t *SchedulingRequestResourceConfig = pucch_Config->schedulingRequestResourceToAddModList->list.array[SR_resource_id]; int SR_period; int SR_offset; - find_period_offest_SR(SchedulingRequestResourceConfig,&SR_period,&SR_offset); + find_period_offset_SR(SchedulingRequestResourceConfig,&SR_period,&SR_offset); int sfn_sf = frame * n_slots_frame + slot; if ((sfn_sf - SR_offset) % SR_period == 0) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 7155a633ee..6f9011e6ed 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1469,7 +1469,7 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra LOG_D(NR_MAC,"[RAPROC] Msg4 r_pucch %d (CCEIndex %d, nb_of_candidates %d, delta_PRI %d)\n", r_pucch, CCEIndex, nr_of_candidates, delta_PRI); - int alloc = nr_acknack_scheduling(module_idP, UE, frameP, slotP, r_pucch, 1); + int alloc = nr_acknack_scheduling(nr_mac, UE, frameP, slotP, r_pucch, 1); if (alloc<0) { LOG_D(NR_MAC,"Couldn't find a pucch allocation for ack nack (msg4) in frame %d slot %d\n",frameP,slotP); return; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 3215ab1764..adba522db9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -508,7 +508,7 @@ bool allocate_dl_retransmission(module_id_t module_id, * allocation after CCE alloc fail would be more complex) */ int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, ul_bwp->pucch_Config, CCEIndex); - const int alloc = nr_acknack_scheduling(module_id, UE, frame, slot, r_pucch, 0); + const int alloc = nr_acknack_scheduling(nr_mac, UE, frame, slot, r_pucch, 0); if (alloc<0) { LOG_D(MAC, "could not find PUCCH for UE %04x@%d.%d\n", @@ -701,7 +701,7 @@ void pf_dl(module_id_t module_id, * allocation after CCE alloc fail would be more complex) */ int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, ul_bwp->pucch_Config, CCEIndex); - const int alloc = nr_acknack_scheduling(module_id, iterator->UE, frame, slot, r_pucch, 0); + const int alloc = nr_acknack_scheduling(mac, iterator->UE, frame, slot, r_pucch, 0); if (alloc<0) { LOG_D(NR_MAC, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 5136c7fc53..6238016cb3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -277,7 +277,7 @@ void nr_preprocessor_phytest(module_id_t module_id, UE->rnti); int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, UE->current_UL_BWP.pucch_Config, CCEIndex); - const int alloc = nr_acknack_scheduling(module_id, UE, frame, slot, r_pucch, 0); + const int alloc = nr_acknack_scheduling(RC.nrmac[module_id], UE, frame, slot, r_pucch, 0); if (alloc < 0) { LOG_D(MAC, "%s(): could not find PUCCH for UE %04x@%d.%d\n", diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 36ba747e72..db4649008c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2210,6 +2210,20 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca } } + +void set_max_fb_time(NR_UE_UL_BWP_t *UL_BWP, const NR_UE_DL_BWP_t *DL_BWP) +{ + UL_BWP->max_fb_time = 8; // default value + // take the maximum in dl_DataToUL_ACK list + if (DL_BWP->dci_format != NR_DL_DCI_FORMAT_1_0 && UL_BWP->pucch_Config) { + const struct NR_PUCCH_Config__dl_DataToUL_ACK *fb_times = UL_BWP->pucch_Config->dl_DataToUL_ACK; + for (int i = 0; i < fb_times->list.count; i++) { + if(*fb_times->list.array[i] > UL_BWP->max_fb_time) + UL_BWP->max_fb_time = *fb_times->list.array[i]; + } + } +} + // main function to configure parameters of current BWP void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_ServingCellConfigCommon_t *scc, @@ -2410,17 +2424,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, if (UL_BWP->csi_MeasConfig) compute_csi_bitlen (UL_BWP->csi_MeasConfig, UE->csi_report_template); - UL_BWP->max_fb_time = 0; - if(DL_BWP->dci_format != NR_DL_DCI_FORMAT_1_0 && - UL_BWP->pucch_Config) { - for (int i=0; ipucch_Config->dl_DataToUL_ACK->list.count; i++) { - if(*UL_BWP->pucch_Config->dl_DataToUL_ACK->list.array[i] > UL_BWP->max_fb_time) - UL_BWP->max_fb_time = *UL_BWP->pucch_Config->dl_DataToUL_ACK->list.array[i]; - } - } - else - UL_BWP->max_fb_time = 8; // default value - + set_max_fb_time(UL_BWP, DL_BWP); set_sched_pucch_list(sched_ctrl, UL_BWP, scc); } @@ -2567,21 +2571,19 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf } void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, - NR_UE_UL_BWP_t *ul_bwp, - NR_ServingCellConfigCommon_t *scc) { + const NR_UE_UL_BWP_t *ul_bwp, + const NR_ServingCellConfigCommon_t *scc) { const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs]; const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; + // PUCCH list size is given by the number of UL slots in the PUCCH period + // the length PUCCH period is determined by max_fb_time since we may need to prepare PUCCH for ACK/NACK max_fb_time slots ahead const int list_size = n_ul_slots_period << (ul_bwp->max_fb_time/nr_slots_period); if(!sched_ctrl->sched_pucch) { - sched_ctrl->sched_pucch = malloc(list_size * sizeof(*sched_ctrl->sched_pucch)); + sched_ctrl->sched_pucch = calloc(list_size, sizeof(*sched_ctrl->sched_pucch)); sched_ctrl->sched_pucch_size = list_size; - for(int i=0; isched_pucch[i]; - memset(curr_pucch, 0, sizeof(*curr_pucch)); - } } else if (list_size > sched_ctrl->sched_pucch_size) { sched_ctrl->sched_pucch = realloc(sched_ctrl->sched_pucch, list_size * sizeof(*sched_ctrl->sched_pucch)); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index f718c6703c..b9373c85cb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -131,6 +131,20 @@ int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = { }; +int get_pucch_index(int slot, int n_slots_frame, const NR_TDD_UL_DL_Pattern_t *tdd, int sched_pucch_size) +{ + // PUCCH structures are indexed by slot in the PUCCH period determined by sched_pucch_size number of UL slots + // this functions return the index to the structure for slot passed to the function + const int first_ul_slot_period = tdd ? tdd->nrofDownlinkSlots : 0; + const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; + const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; + // ((slot % nr_slots_period) - first_ul_slot_period) gives the progressive number of the slot in a TDD period + // ((slot / nr_slots_period) * n_ul_slots_period) adds up the number of UL slots in the previous TDD periods + // the sum gives the index of current UL slot in the frame which is normalized wrt sched_pucch_size + return ((slot % nr_slots_period) - first_ul_slot_period + (slot / nr_slots_period) * n_ul_slots_period) % sched_pucch_size; + +} + void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP) @@ -140,20 +154,25 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac, UE_iterator(nrmac->UE_info.list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - for (int i = 0; i < sched_ctrl->sched_pucch_size; i++) { - NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[i]; - const uint16_t O_ack = curr_pucch->dai_c; - const uint16_t O_csi = curr_pucch->csi_bits; - const uint8_t O_sr = curr_pucch->sr_flag; - if (curr_pucch->active == true && - frameP == curr_pucch->frame && - slotP == curr_pucch->ul_slot) { - LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %04x in %4d.%2d O_ack %d, O_sr %d, O_csi %d\n", - i,UE->rnti,curr_pucch->frame,curr_pucch->ul_slot,O_ack,O_sr,O_csi); - nr_fill_nfapi_pucch(nrmac, frameP, slotP, curr_pucch, UE); - memset(curr_pucch, 0, sizeof(*curr_pucch)); - } - } + NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; + const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs]; + const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[0].ServingCellConfigCommon; + const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; + AssertFatal(tdd || nrmac->common_channels[0].frame_type == FDD, "Dynamic TDD not handled yet\n"); + const int pucch_index = get_pucch_index(slotP, n_slots_frame, tdd, sched_ctrl->sched_pucch_size); + NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index]; + if (!curr_pucch->active) + continue; + DevAssert(frameP == curr_pucch->frame && slotP == curr_pucch->ul_slot); + + const uint16_t O_ack = curr_pucch->dai_c; + const uint16_t O_csi = curr_pucch->csi_bits; + const uint8_t O_sr = curr_pucch->sr_flag; + LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %04x in %4d.%2d O_ack %d, O_sr %d, O_csi %d\n", + pucch_index,UE->rnti,curr_pucch->frame,curr_pucch->ul_slot,O_ack,O_sr,O_csi); + nr_fill_nfapi_pucch(nrmac, frameP, slotP, curr_pucch, UE); + memset(curr_pucch, 0, sizeof(*curr_pucch)); + } } @@ -207,10 +226,7 @@ void nr_csi_meas_reporting(int Mod_idP, const NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels[0].ServingCellConfigCommon; const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; AssertFatal(tdd || RC.nrmac[Mod_idP]->common_channels[0].frame_type == FDD, "Dynamic TDD not handled yet\n"); - const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int first_ul_slot_period = tdd ? tdd->nrofDownlinkSlots : 0; - const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; - const int pucch_index = ((sched_slot % nr_slots_period) - first_ul_slot_period + (sched_slot / nr_slots_period) * n_ul_slots_period) % sched_ctrl->sched_pucch_size; + const int pucch_index = get_pucch_index(sched_slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size); NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index]; AssertFatal(curr_pucch->active == false, "CSI structure is scheduled in advance. It should be free!\n"); curr_pucch->r_pucch = -1; @@ -995,17 +1011,12 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, } } -bool test_pucch0_vrb_occupation(NR_UE_sched_ctrl_t *sched_ctrl, - NR_sched_pucch_t *pucch, - uint16_t *vrb_map_UL, - const NR_ServingCellConfigCommon_t *scc, - NR_PUCCH_Config_t *pucch_Config, - int r_pucch, - int bwp_start, - int bwp_size) { - - // We assume initial cyclic shift is always 0 so different pucch resources can't overlap - +void set_pucch_allocation(const NR_PUCCH_Config_t *pucch_Config, + const NR_ServingCellConfigCommon_t *scc, + const int r_pucch, + const int bwp_size, + NR_sched_pucch_t *pucch) +{ if(r_pucch<0){ const NR_PUCCH_Resource_t *resource = pucch_Config->resourceToAddModList->list.array[0]; DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0); @@ -1024,6 +1035,14 @@ bool test_pucch0_vrb_occupation(NR_UE_sched_ctrl_t *sched_ctrl, &pucch->nr_of_symb, &pucch->start_symb); } +} + +bool test_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, + uint16_t *vrb_map_UL, + const int bwp_start, + const int bwp_size) { + + // We assume initial cyclic shift is always 0 so different pucch resources can't overlap // verifying occupation of PRBs for ACK/NACK on dedicated pucch for (int l=0; lnr_of_symb; l++) { @@ -1041,9 +1060,24 @@ bool test_pucch0_vrb_occupation(NR_UE_sched_ctrl_t *sched_ctrl, return true; } +void set_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, + uint16_t *vrb_map_UL, + const int bwp_start) +{ + for (int l=0; lnr_of_symb; l++) { + uint16_t symb = SL_to_bitmap(pucch->start_symb+l, 1); + int prb; + if (l==1 && pucch->second_hop_prb != 0) + prb = pucch->second_hop_prb; + else + prb = pucch->prb_start; + vrb_map_UL[bwp_start+prb] |= symb; + } +} + // this function returns an index to NR_sched_pucch structure // if the function returns -1 it was not possible to schedule acknack -int nr_acknack_scheduling(int mod_id, +int nr_acknack_scheduling(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t frame, sub_frame_t slot, @@ -1052,27 +1086,20 @@ int nr_acknack_scheduling(int mod_id, { const int CC_id = 0; - const int minfbtime = RC.nrmac[mod_id]->minRXTXTIMEpdsch; - const NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels[CC_id].ServingCellConfigCommon; + const int minfbtime = mac->minRXTXTIMEpdsch; + const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon; const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs]; const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - AssertFatal(tdd || RC.nrmac[mod_id]->common_channels[CC_id].frame_type == FDD, "Dynamic TDD not handled yet\n"); + AssertFatal(tdd || mac->common_channels[CC_id].frame_type == FDD, "Dynamic TDD not handled yet\n"); const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; const int first_ul_slot_period = tdd ? tdd->nrofDownlinkSlots : 0; - const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; - /* for the moment, we consider: - * * only pucch_sched[0] holds HARQ (and SR) - * * we do not multiplex with CSI, which is always in pucch_sched[2] - * * SR uses format 0 and is allocated in the first UL (mixed) slot (and not - * later) - * * each UE has dedicated PUCCH Format 0 resources, and we use index 0! */ NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config; - int bwp_start = ul_bwp->BWPStart; - int bwp_size = ul_bwp->BWPSize; + const int bwp_start = ul_bwp->BWPStart; + const int bwp_size = ul_bwp->BWPSize; nr_dci_format_t dci_format = NR_DL_DCI_FORMAT_1_0; if(is_common == 0) @@ -1090,7 +1117,8 @@ int nr_acknack_scheduling(int mod_id, if(pucch_slot%nr_slots_period < first_ul_slot_period) continue; const int pucch_frame = (frame + ((slot + pdsch_to_harq_feedback[f]) / n_slots_frame)) & 1023; - const int pucch_index = ((pucch_slot % nr_slots_period) - first_ul_slot_period + (pucch_slot / nr_slots_period) * n_ul_slots_period) % sched_ctrl->sched_pucch_size; + // we store PUCCH resources according to slot, TDD configuration and size of the vector containing PUCCH structures + const int pucch_index = get_pucch_index(pucch_slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size); NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index]; if (curr_pucch->active && curr_pucch->frame == pucch_frame && @@ -1102,8 +1130,8 @@ int nr_acknack_scheduling(int mod_id, curr_pucch->dai_c == 2) continue; // if there is CSI but simultaneous HARQ+CSI is disable we can't schedule - if(!curr_pucch->simultaneous_harqcsi && - curr_pucch->csi_bits>0) + if(curr_pucch->csi_bits > 0 && + !curr_pucch->simultaneous_harqcsi) continue; // TODO we can't schedule more than 11 bits in PUCCH2 for now if (curr_pucch->csi_bits + curr_pucch->dai_c >= 10) @@ -1118,19 +1146,15 @@ int nr_acknack_scheduling(int mod_id, return pucch_index; // index of current PUCCH structure } else if (curr_pucch->active) { - LOG_E(NR_MAC, "This shouldn't happen! curr_pucch frame.slot %d.%d not matching with computed frame.slot %d.%d\n", - curr_pucch->frame, curr_pucch->ul_slot, pucch_frame, pucch_slot); - continue; + AssertFatal(1==0, "This shouldn't happen! curr_pucch frame.slot %d.%d not matching with computed frame.slot %d.%d\n", + curr_pucch->frame, curr_pucch->ul_slot, pucch_frame, pucch_slot); } else { // unoccupied occasion // checking if in ul_slot the resources potentially to be assigned to this PUCCH are available - uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch_slot * MAX_BWP_SIZE]; - bool ret = test_pucch0_vrb_occupation(sched_ctrl, - curr_pucch, + set_pucch_allocation(pucch_Config, scc, r_pucch, bwp_size, curr_pucch); + uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[pucch_slot * MAX_BWP_SIZE]; + bool ret = test_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, - scc, - pucch_Config, - r_pucch, bwp_start, bwp_size); if(!ret) { @@ -1151,13 +1175,7 @@ int nr_acknack_scheduling(int mod_id, frame,slot,curr_pucch->frame,curr_pucch->ul_slot,pucch_index,f,curr_pucch->dai_c); // blocking resources for current PUCCH in VRB map - for (int l=0; lnr_of_symb; l++) { - uint16_t symb = SL_to_bitmap(curr_pucch->start_symb+l, 1); - int prb = curr_pucch->prb_start; - if (l==1 && curr_pucch->second_hop_prb != 0) - prb = curr_pucch->second_hop_prb; - vrb_map_UL[bwp_start+prb] |= symb; - } + set_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start); return pucch_index; // index of current PUCCH structure } @@ -1171,7 +1189,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) { if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slot / 64], slot)) return; - int CC_id = 0; + const int CC_id = 0; UE_iterator(nrmac->UE_info.list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; @@ -1189,13 +1207,13 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) int SR_period; int SR_offset; - find_period_offest_SR(SchedulingRequestResourceConfig,&SR_period,&SR_offset); + find_period_offset_SR(SchedulingRequestResourceConfig,&SR_period,&SR_offset); // convert to int to avoid underflow of uint int sfn_sf = SFN * n_slots_frame + slot; LOG_D(NR_MAC,"SR_resource_id %d: SR_period %d, SR_offset %d\n",SR_resource_id,SR_period,SR_offset); if ((sfn_sf - SR_offset) % SR_period != 0) continue; - LOG_D(NR_MAC, "%4d.%2d Scheduling Request identified\n", SFN, slot); + LOG_D(NR_MAC, "%4d.%2d Scheduling Request UE %04x identified\n", SFN, slot, UE->rnti); NR_PUCCH_ResourceId_t *PucchResourceId = SchedulingRequestResourceConfig->resource; int idx = -1; @@ -1210,10 +1228,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; AssertFatal(tdd || nrmac->common_channels[CC_id].frame_type == FDD, "Dynamic TDD not handled yet\n"); - const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int first_ul_slot_period = tdd ? tdd->nrofDownlinkSlots : 0; - const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; - const int pucch_index = ((slot % nr_slots_period) - first_ul_slot_period + (slot / nr_slots_period) * n_ul_slots_period) % sched_ctrl->sched_pucch_size; + const int pucch_index = get_pucch_index(slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size); NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index]; if (curr_pucch->active && @@ -1222,20 +1237,17 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) curr_pucch->resource_indicator == idx) curr_pucch->sr_flag = true; else if (curr_pucch->active) { - LOG_E(NR_MAC, "This shouldn't happen! curr_pucch frame.slot %d.%d not matching with SR function frame.slot %d.%d\n", - curr_pucch->frame, curr_pucch->ul_slot, SFN, slot); + AssertFatal(1==0, "This shouldn't happen! curr_pucch frame.slot %d.%d not matching with SR function frame.slot %d.%d\n", + curr_pucch->frame, curr_pucch->ul_slot, SFN, slot); continue; } else { uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[slot * MAX_BWP_SIZE]; - int bwp_start = ul_bwp->BWPStart; - int bwp_size = ul_bwp->BWPSize; - bool ret = test_pucch0_vrb_occupation(sched_ctrl, - curr_pucch, + const int bwp_start = ul_bwp->BWPStart; + const int bwp_size = ul_bwp->BWPSize; + set_pucch_allocation(pucch_Config, scc, -1, bwp_size, curr_pucch); + bool ret = test_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, - scc, - pucch_Config, - -1, bwp_start, bwp_size); if (!ret) { @@ -1248,15 +1260,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) curr_pucch->resource_indicator = idx; curr_pucch->r_pucch = -1; curr_pucch->active = true; - for (int l=0; lnr_of_symb; l++) { - uint16_t symb = SL_to_bitmap(curr_pucch->start_symb+l, 1); - int prb; - if (l==1 && curr_pucch->second_hop_prb != 0) - prb = curr_pucch->second_hop_prb; - else - prb = curr_pucch->prb_start; - vrb_map_UL[bwp_start+prb] |= symb; - } + set_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start); } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 2e3ccf4ba6..a322c4917b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -209,7 +209,7 @@ void nr_csi_meas_reporting(int Mod_idP, frame_t frameP, sub_frame_t slotP); -int nr_acknack_scheduling(int Mod_idP, +int nr_acknack_scheduling(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t frameP, sub_frame_t slotP, @@ -466,8 +466,8 @@ uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx); uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format); void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, - NR_UE_UL_BWP_t *ul_bwp, - NR_ServingCellConfigCommon_t *scc); + const NR_UE_UL_BWP_t *ul_bwp, + const NR_ServingCellConfigCommon_t *scc); const int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot); const int get_ul_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 17f0504e15..b28fd0ffee 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -563,8 +563,9 @@ typedef struct { int cce_index; uint8_t aggregation_level; - /// Array of PUCCH scheduling information. + /// Array of PUCCH scheduling information /// Its size depends on TDD configuration and max feedback time + /// There will be a structure for each UL slot in the active period determined by the size NR_sched_pucch_t *sched_pucch; int sched_pucch_size;