diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index d4cde4f3c34c29dafd9e7e7ca10bfca1579f1f3c..599f95a72fa8a9efd770e42ec23633fa91d0d2f0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -591,31 +591,9 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, if (CellGroup) { - if (get_softmodem_params()->sa) { - calculate_preferred_dl_tda(Mod_idP, NULL); - } - const NR_ServingCellConfig_t *servingCellConfig = NULL; - if(CellGroup->spCellConfig && CellGroup->spCellConfig->spCellConfigDedicated) { + if(CellGroup->spCellConfig && CellGroup->spCellConfig->spCellConfigDedicated) servingCellConfig = CellGroup->spCellConfig->spCellConfigDedicated; - const struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = servingCellConfig->downlinkBWP_ToAddModList; - if(bwpList) { - AssertFatal(bwpList->list.count > 0, "downlinkBWP_ToAddModList has no BWPs!\n"); - for (int i = 0; i < bwpList->list.count; ++i) { - const NR_BWP_Downlink_t *bwp = bwpList->list.array[i]; - calculate_preferred_dl_tda(Mod_idP, bwp); - } - } - - const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = servingCellConfig->uplinkConfig->uplinkBWP_ToAddModList; - if(ubwpList) { - AssertFatal(ubwpList->list.count > 0, "uplinkBWP_ToAddModList no BWPs!\n"); - for (int i = 0; i < ubwpList->list.count; ++i) { - const NR_BWP_Uplink_t *ubwp = ubwpList->list.array[i]; - calculate_preferred_ul_tda(Mod_idP, ubwp); - } - } - } NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; if (add_ue == 1 && get_softmodem_params()->phy_test) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index b4732de1a31e7a5214412d0045c7abeadd9d57de..19db162d96a499dac4da86240d388052a6e6608e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1198,20 +1198,13 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu); } -void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) -{ +void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; if ((ra->Msg2_frame == frameP) && (ra->Msg2_slot == slotP)) { - //TODO time domain assignment for msg2 needs to be improved - uint8_t time_domain_assignment; - if(cc->frame_type == TDD) - time_domain_assignment = 1; - else - time_domain_assignment = 0; int mcsIndex = -1; // initialization value int rbStart = 0; int rbSize = 8; @@ -1251,6 +1244,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra } // Calculate number of symbols + int time_domain_assignment = get_dl_tda(nr_mac, scc, slotP); int startSymbolIndex, nrOfSymbols; const int startSymbolAndLength = pdsch_TimeDomainAllocationList->list.array[time_domain_assignment]->startSymbolAndLength; SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index aab77c515a2c291d77593048838ad345b202d1ac..4fc4eae1a27c229d4c590fbee93e1b4e07eb325a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -53,105 +53,22 @@ #define WORD 32 //#define SIZE_OF_POINTER sizeof (void *) -void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *bwp) { - gNB_MAC_INST *nrmac = RC.nrmac[module_id]; - const int bwp_id = bwp ? bwp->bwp_Id : 0; +const int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot) { - if (nrmac->preferred_dl_tda[bwp_id]) - return; + 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->frame_type == FDD, "Dynamic TDD not handled yet\n"); - /* there is a mixed slot only when in TDD */ - NR_ServingCellConfigCommon_t *scc = nrmac->common_channels->ServingCellConfigCommon; - frame_type_t frame_type = nrmac->common_channels->frame_type; - const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - const NR_TDD_UL_DL_Pattern_t *tdd = - scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - int symb_dlMixed = 0; - int nr_mix_slots = 0; - int nr_slots_period = n; - - if (tdd) { - symb_dlMixed = (1 << tdd->nrofDownlinkSymbols) - 1; - nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0; - nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity); - } else - // if TDD configuration is not present and the band is not FDD, it means it is a dynamic TDD configuration - AssertFatal(nrmac->common_channels->frame_type == FDD,"Dynamic TDD not handled yet\n"); - - int target_ss; - - if (bwp) { - target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; - } else { - target_ss = NR_SearchSpace__searchSpaceType_PR_common; - } + // Use special TDA in case of CSI-RS + const NR_UE_info_t *UE_info = &nrmac->UE_info; + if(UE_info->sched_csirs) + return 1; - const NR_SIB1_t *sib1 = nrmac->common_channels[0].sib1 ? nrmac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL; - NR_SearchSpace_t *search_space = get_searchspace(sib1, - scc, - bwp ? bwp->bwp_Dedicated : NULL, - target_ss); - - NR_ControlResourceSet_t *coreset = get_coreset(module_id, scc, bwp ? bwp->bwp_Dedicated : NULL, search_space, target_ss); - // get coreset symbol "map" - const uint16_t symb_coreset = (1 << coreset->duration) - 1; - - NR_PDSCH_TimeDomainResourceAllocationList_t *tdaList = get_pdsch_TimeDomainAllocationList(bwp, - scc, - sib1); - AssertFatal(tdaList->list.count >= 1, "need to have at least one TDA for DL slots\n"); - - /* check that TDA index 0 fits into DL and does not overlap CORESET */ - const NR_PDSCH_TimeDomainResourceAllocation_t *tdaP_DL = tdaList->list.array[0]; - AssertFatal(!tdaP_DL->k0 || *tdaP_DL->k0 == 0, - "TimeDomainAllocation at index 1: non-null k0 (%ld) is not supported by the scheduler\n", - *tdaP_DL->k0); - int start, len; - SLIV2SL(tdaP_DL->startSymbolAndLength, &start, &len); - const uint16_t symb_tda = ((1 << len) - 1) << start; - // check whether coreset and TDA overlap: then we cannot use it. Note that - // here we assume that the coreset is scheduled every slot (which it - // currently is) and starting at symbol 0 - AssertFatal((symb_coreset & symb_tda) == 0, "TDA index 0 for DL overlaps with CORESET\n"); - /* check that TDA index 1 fits into DL part of mixed slot, if it exists */ - int tdaMi = -1; - - if (frame_type == TDD && tdaList->list.count > 1) { - const NR_PDSCH_TimeDomainResourceAllocation_t *tdaP_Mi = tdaList->list.array[1]; - AssertFatal(!tdaP_Mi->k0 || *tdaP_Mi->k0 == 0, - "TimeDomainAllocation at index 1: non-null k0 (%ld) is not supported by the scheduler\n", - *tdaP_Mi->k0); - int start, len; - SLIV2SL(tdaP_Mi->startSymbolAndLength, &start, &len); - const uint16_t symb_tda = ((1 << len) - 1) << start; - - // check whether coreset and TDA overlap: then, we cannot use it. Also, - // check whether TDA is entirely within mixed slot DL. Note that - // here we assume that the coreset is scheduled every slot (which it - // currently is) - if ((symb_coreset & symb_tda) == 0 && (symb_dlMixed & symb_tda) == symb_tda) { - tdaMi = 1; - } else { - LOG_E(MAC, - "TDA index 1 DL overlaps with CORESET or is not entirely in mixed slot (symb_coreset %x symb_dlMixed %x symb_tda %x), won't schedule DL mixed slot\n", - symb_coreset, - symb_dlMixed, - symb_tda); - } - } - - nrmac->preferred_dl_tda[bwp_id] = malloc(n * sizeof(*nrmac->preferred_dl_tda[bwp_id])); - - for (int i = 0; i < n; ++i) { - nrmac->preferred_dl_tda[bwp_id][i] = -1; - - if (frame_type == FDD || i % nr_slots_period < tdd->nrofDownlinkSlots) - nrmac->preferred_dl_tda[bwp_id][i] = 0; - else if (nr_mix_slots && i % nr_slots_period == tdd->nrofDownlinkSlots) - nrmac->preferred_dl_tda[bwp_id][i] = tdaMi; - - LOG_D(MAC, "slot %d preferred_dl_tda %d\n", i, nrmac->preferred_dl_tda[bwp_id][i]); + if (tdd && tdd->nrofDownlinkSymbols > 1) { // if there is a mixed slot where we can transmit DL + const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + 1; + if ((slot%nr_slots_period) == tdd->nrofDownlinkSlots) + return 2; } + return 0; // if FDD or not mixed slot in TDD, for now use default TDA (TODO handle CSI-RS slots) } // Compute and write all MAC CEs and subheaders, and return number of written @@ -491,7 +408,7 @@ bool allocate_dl_retransmission(module_id_t module_id, int rbStart = 0; // start wrt BWPstart NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; int rbSize = 0; - const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0][slot]; + const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot); AssertFatal(tda>=0,"Unable to find PDSCH time domain allocation in list\n"); if (tda == retInfo->time_domain_allocation) { @@ -838,7 +755,7 @@ void pf_dl(module_id_t module_id, if (max_num_ue < 0) return; /* MCS has been set above */ - const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0][slot]; + const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot); AssertFatal(tda>=0,"Unable to find PDSCH time domain allocation in list\n"); NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; @@ -910,12 +827,7 @@ void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t /* This is temporary and it assumes all UEs have the same BWP and TDA*/ int UE_id = UE_info->list.head; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - const int bwp_id = sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0; - - if (!RC.nrmac[module_id]->preferred_dl_tda[bwp_id]) - return; - - const int tda = RC.nrmac[module_id]->preferred_dl_tda[bwp_id][slot]; + const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot); int startSymbolIndex, nrOfSymbols; const struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList = sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList : diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 33dd96d9bf19128aa218115a9f15e6b9fe66d966..8cca07a51a9b142ad9896911b835536c29008947 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -275,7 +275,8 @@ void nr_preprocessor_phytest(module_id_t module_id, __func__, UE_id); NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - const int tda = sched_ctrl->active_bwp ? RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp->bwp_Id][slot] : 1; + + const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot); NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; ps->nrOfLayers = target_dl_Nl; if (ps->time_domain_allocation != tda || ps->nrOfLayers != target_dl_Nl) @@ -435,18 +436,25 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - const int tda = sched_ctrl->active_ubwp ? RC.nrmac[module_id]->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 1; - if (tda < 0) - return false; const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList = sched_ctrl->active_ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; - AssertFatal(tda < tdaList->list.count, + const int temp_tda = get_ul_tda(nr_mac, scc, slot); + if (temp_tda < 0) + return false; + AssertFatal(temp_tda < tdaList->list.count, "time domain assignment %d >= %d\n", - tda, + temp_tda, tdaList->list.count); - int K2 = get_K2(scc,NULL,sched_ctrl->active_ubwp, tda, mu); + int K2 = get_K2(scc,NULL,sched_ctrl->active_ubwp, temp_tda, mu); const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]); const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; + const int tda = get_ul_tda(nr_mac, scc, sched_slot); + if (tda < 0) + return false; + AssertFatal(tda < tdaList->list.count, + "time domain assignment %d >= %d\n", + tda, + tdaList->list.count); /* check if slot is UL, and that slot is 8 (assuming K2=6 because of UE * limitations). Note that if K2 or the TDD configuration is changed, below * conditions might exclude each other and never be true */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 9141bc78b43979337a8a2a72e4b7417071b486e9..1e749a95923d9251bc2bc077df9c3c42105d6cff 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2697,6 +2697,8 @@ void nr_csirs_scheduling(int Mod_idP, gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP]; uint16_t *vrb_map = gNB_mac->common_channels[CC_id].vrb_map; + UE_info->sched_csirs = false; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; @@ -2729,6 +2731,7 @@ void nr_csirs_scheduling(int Mod_idP, if((frame*n_slots_frame+slot-offset)%period == 0) { LOG_D(NR_MAC,"Scheduling CSI-RS in frame %d slot %d\n",frame,slot); + UE_info->sched_csirs = true; nfapi_nr_dl_tti_request_pdu_t *dl_tti_csirs_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset((void*)dl_tti_csirs_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); @@ -2896,6 +2899,7 @@ void nr_csirs_scheduling(int Mod_idP, void nr_mac_update_timers(module_id_t module_id, frame_t frame, sub_frame_t slot) { + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; const NR_list_t *UE_list = &UE_info->list; for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { @@ -2932,12 +2936,11 @@ void nr_mac_update_timers(module_id_t module_id, cg->spCellConfig && cg->spCellConfig->spCellConfigDedicated ? cg->spCellConfig->spCellConfigDedicated->initialDownlinkBWP : NULL; - int **preferred_dl_tda = RC.nrmac[module_id]->preferred_dl_tda; + NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; const uint8_t layers = set_dl_nrOfLayers(sched_ctrl); - const int tda = bwp && preferred_dl_tda[bwp->bwp_Id][slot] >= 0 ? - preferred_dl_tda[bwp->bwp_Id][slot] : (ps->time_domain_allocation >= 0 ? ps->time_domain_allocation : 0); + const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot); nr_set_pdsch_semi_static(sib1, scc, @@ -2955,14 +2958,13 @@ void nr_mac_update_timers(module_id_t module_id, cg->spCellConfig->spCellConfigDedicated && cg->spCellConfig->spCellConfigDedicated->uplinkConfig ? cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP : NULL; - int **preferred_ul_tda = RC.nrmac[module_id]->preferred_ul_tda; + NR_pusch_semi_static_t *ups = &sched_ctrl->pusch_semi_static; int dci_format = get_dci_format(sched_ctrl); const uint8_t num_dmrs_cdm_grps_no_data = (ubwp || ubwpd) ? 1 : 2; const uint8_t nrOfLayers = 1; - const int utda = ubwp && preferred_ul_tda[ubwp->bwp_Id][slot] >= 0 ? - preferred_ul_tda[ubwp->bwp_Id][slot] : (ups->time_domain_allocation >= 0 ? ups->time_domain_allocation : 0); + const int utda = get_ul_tda(RC.nrmac[module_id], scc, slot); nr_set_pusch_semi_static(sib1, scc, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 747808bfa893e100f43158e4e3371d6a8fda2a8a..591a549c0a21bb898bd9cae727c66d21630bdf18 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -46,138 +46,18 @@ int get_dci_format(NR_UE_sched_ctrl_t *sched_ctrl) { return(dci_format); } -void calculate_preferred_ul_tda(module_id_t module_id, const NR_BWP_Uplink_t *ubwp) -{ - gNB_MAC_INST *nrmac = RC.nrmac[module_id]; - const int bwp_id = ubwp->bwp_Id; - if (nrmac->preferred_ul_tda[bwp_id]) - return; +const int get_ul_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot) { /* there is a mixed slot only when in TDD */ - NR_ServingCellConfigCommon_t *scc = nrmac->common_channels->ServingCellConfigCommon; - frame_type_t frame_type = nrmac->common_channels->frame_type; - const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - - NR_ServingCellConfigCommonSIB_t *scc_sib1 = nrmac->common_channels[0].sib1 ? - RC.nrmac[module_id]->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1->servingCellConfigCommon : NULL; - - AssertFatal(scc!=NULL || scc_sib1!=NULL,"We need one serving cell config common\n"); - - const int mu = scc ? scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing : - scc_sib1->uplinkConfigCommon->initialUplinkBWP.genericParameters.subcarrierSpacing; - - NR_TDD_UL_DL_Pattern_t *tdd = NULL; - if (scc && scc->tdd_UL_DL_ConfigurationCommon) { - tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; - } else if (scc_sib1 && scc_sib1->tdd_UL_DL_ConfigurationCommon) { - tdd = &scc_sib1->tdd_UL_DL_ConfigurationCommon->pattern1; - } + 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->frame_type == FDD, "Dynamic TDD not handled yet\n"); - /* Uplink symbols are at the end of the slot */ - int symb_ulMixed = 0; - int nr_mix_slots = 0; - int nr_slots_period = n; - if (tdd) { - symb_ulMixed = ((1 << tdd->nrofUplinkSymbols) - 1) << (14 - tdd->nrofUplinkSymbols); - nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0; - nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity); - } - else - // if TDD configuration is not present and the band is not FDD, it means it is a dynamic TDD configuration - AssertFatal(nrmac->common_channels->frame_type == FDD,"Dynamic TDD not handled yet\n"); - - const struct NR_PUCCH_Config__resourceToAddModList *resList = ubwp->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList; - // for the moment, just block any symbol that might hold a PUCCH, regardless - // of the RB. This is a big simplification, as most RBs will NOT have a PUCCH - // in the respective symbols, but it simplifies scheduling - uint16_t symb_pucch = 0; - for (int i = 0; i < resList->list.count; ++i) { - const NR_PUCCH_Resource_t *resource = resList->list.array[i]; - int nrofSymbols = 0; - int startingSymbolIndex = 0; - switch (resource->format.present) { - case NR_PUCCH_Resource__format_PR_format0: - nrofSymbols = resource->format.choice.format0->nrofSymbols; - startingSymbolIndex = resource->format.choice.format0->startingSymbolIndex; - break; - case NR_PUCCH_Resource__format_PR_format1: - nrofSymbols = resource->format.choice.format1->nrofSymbols; - startingSymbolIndex = resource->format.choice.format1->startingSymbolIndex; - break; - case NR_PUCCH_Resource__format_PR_format2: - nrofSymbols = resource->format.choice.format2->nrofSymbols; - startingSymbolIndex = resource->format.choice.format2->startingSymbolIndex; - break; - case NR_PUCCH_Resource__format_PR_format3: - nrofSymbols = resource->format.choice.format3->nrofSymbols; - startingSymbolIndex = resource->format.choice.format3->startingSymbolIndex; - break; - case NR_PUCCH_Resource__format_PR_format4: - nrofSymbols = resource->format.choice.format4->nrofSymbols; - startingSymbolIndex = resource->format.choice.format4->startingSymbolIndex; - break; - default: - AssertFatal(0, "found NR_PUCCH format index %d\n", resource->format.present); - break; - } - symb_pucch |= ((1 << nrofSymbols) - 1) << startingSymbolIndex; - } - - /* check that TDA index 1 fits into UL slot and does not overlap with PUCCH */ - const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; - const NR_PUSCH_TimeDomainResourceAllocation_t *tdaP_UL = tdaList->list.array[0]; - const int k2 = get_K2(scc, scc_sib1, (NR_BWP_Uplink_t*)ubwp,0, mu); - int start, len; - SLIV2SL(tdaP_UL->startSymbolAndLength, &start, &len); - const uint16_t symb_tda = ((1 << len) - 1) << start; - // check whether PUCCH and TDA overlap: then, we cannot use it. Note that - // here we assume that the PUCCH is scheduled in every slot, and on all RBs - // (which is mostly not true, this is a simplification) - AssertFatal((symb_pucch & symb_tda) == 0, "TDA index 0 for UL overlaps with PUCCH\n"); - - // get largest time domain allocation (TDA) for UL slot and UL in mixed slot - int tdaMi = -1; - if (nr_mix_slots>0) { - const NR_PUSCH_TimeDomainResourceAllocation_t *tdaP_Mi = tdaList->list.array[1]; - AssertFatal(k2 == get_K2(scc, scc_sib1, (NR_BWP_Uplink_t*)ubwp, 1, mu), - "scheduler cannot handle different k2 for UL slot (%d) and UL Mixed slot (%ld)\n", - k2, - get_K2(scc, scc_sib1, (NR_BWP_Uplink_t*)ubwp, 1, mu)); - SLIV2SL(tdaP_Mi->startSymbolAndLength, &start, &len); - const uint16_t symb_tda_mi = ((1 << len) - 1) << start; - // check whether PUCCH and TDA overlap: then, we cannot use it. Also, check - // whether TDA is entirely within mixed slot, UL. Note that here we assume - // that the PUCCH is scheduled in every slot, and on all RBs (which is - // mostly not true, this is a simplification) - if ((symb_pucch & symb_tda_mi) == 0 && (symb_ulMixed & symb_tda_mi) == symb_tda_mi) { - tdaMi = 1; - } else { - LOG_E(NR_MAC, - "TDA index 1 UL overlaps with PUCCH or is not entirely in mixed slot (symb_pucch %x symb_ulMixed %x symb_tda_mi %x), won't schedule UL mixed slot\n", - symb_pucch, - symb_ulMixed, - symb_tda_mi); - } - } - - nrmac->preferred_ul_tda[bwp_id] = malloc(n * sizeof(*nrmac->preferred_ul_tda[bwp_id])); - - for (int slot = 0; slot < n; ++slot) { - const int sched_slot = (slot + k2) % n; - nrmac->preferred_ul_tda[bwp_id][slot] = -1; - if (frame_type == FDD || sched_slot % nr_slots_period >= tdd->nrofDownlinkSlots + nr_mix_slots) - nrmac->preferred_ul_tda[bwp_id][slot] = 0; - else if (nr_mix_slots && sched_slot % nr_slots_period == tdd->nrofDownlinkSlots) - nrmac->preferred_ul_tda[bwp_id][slot] = tdaMi; - LOG_D(MAC, "DL slot %d UL slot %d preferred_ul_tda %d\n", slot, sched_slot, nrmac->preferred_ul_tda[bwp_id][slot]); - } - - if (tdd && k2 < tdd->nrofUplinkSlots) { - LOG_W(NR_MAC, - "k2 %d < tdd->nrofUplinkSlots %ld: not all UL slots can be scheduled\n", - k2, - tdd->nrofUplinkSlots); + if (tdd && tdd->nrofUplinkSymbols > 1) { // if there is uplink symbols in mixed slot + const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + 1; + if ((slot%nr_slots_period) == tdd->nrofDownlinkSlots) + return 1; } + return 0; // if FDD or not mixed slot in TDD, for now use default TDA (TODO handle CSI-RS slots) } // For both UL-SCH except: @@ -980,7 +860,7 @@ bool allocate_ul_retransmission(module_id_t module_id, const uint16_t bwpSize = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); const uint8_t nrOfLayers = 1; const uint8_t num_dmrs_cdm_grps_no_data = (sched_ctrl->active_bwp || ubwpd) ? 1 : 2; - const int tda = sched_ctrl->active_ubwp ? RC.nrmac[module_id]->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0; + const int tda = get_ul_tda(nr_mac, scc, retInfo->slot); LOG_D(NR_MAC,"retInfo->time_domain_allocation = %d, tda = %d\n", retInfo->time_domain_allocation, tda); LOG_D(NR_MAC,"num_dmrs_cdm_grps_no_data %d, tbs %d\n",num_dmrs_cdm_grps_no_data, retInfo->tb_size); if (tda == retInfo->time_domain_allocation) { @@ -1254,7 +1134,7 @@ void pf_ul(module_id_t module_id, const uint8_t nrOfLayers = 1; const uint8_t num_dmrs_cdm_grps_no_data = (sched_ctrl->active_ubwp || ubwpd) ? 1 : 2; int dci_format = get_dci_format(sched_ctrl); - const int tda = sched_ctrl->active_ubwp ? nrmac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0; + const int tda = get_ul_tda(nrmac, scc, sched_pusch->slot); if (ps->time_domain_allocation != tda || ps->dci_format != dci_format || ps->nrOfLayers != nrOfLayers @@ -1393,7 +1273,7 @@ void pf_ul(module_id_t module_id, const uint8_t nrOfLayers = 1; const uint8_t num_dmrs_cdm_grps_no_data = (sched_ctrl->active_ubwp || ubwpd) ? 1 : 2; int dci_format = get_dci_format(sched_ctrl); - const int tda = sched_ctrl->active_ubwp ? nrmac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0; + const int tda = get_ul_tda(nrmac, scc, sched_pusch->slot); if (ps->time_domain_allocation != tda || ps->dci_format != dci_format || ps->nrOfLayers != nrOfLayers @@ -1486,12 +1366,14 @@ bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t * schedule now (slot + k2 is not UL slot) */ int UE_id = UE_info->list.head; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - const int tda = sched_ctrl->active_ubwp ? nr_mac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0; - if (tda < 0) - return false; - int K2 = get_K2(scc, scc_sib1, sched_ctrl->active_ubwp, tda, mu); + const int temp_tda = get_ul_tda(nr_mac, scc, slot); + int K2 = get_K2(scc, scc_sib1, sched_ctrl->active_ubwp, temp_tda, mu); const int sched_frame = (frame + (slot + K2 >= nr_slots_per_frame[mu])) & 1023; const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; + const int tda = get_ul_tda(nr_mac, scc, sched_slot); + if (tda < 0) + return false; + DevAssert(K2 == get_K2(scc, scc_sib1, sched_ctrl->active_ubwp, tda, mu)); if (!is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) return false; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index da234fe30a2ef76b397c79eb2ccf8dfe93ec6698..f568cf3f6500db888abb2eb0970519c0b818dacc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -512,8 +512,8 @@ uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx); uint8_t set_dl_nrOfLayers(NR_UE_sched_ctrl_t *sched_ctrl); int get_dci_format(NR_UE_sched_ctrl_t *sched_ctrl); -void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *bwp); -void calculate_preferred_ul_tda(module_id_t module_id, const NR_BWP_Uplink_t *ubwp); +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); bool find_free_CCE(module_id_t module_id, sub_frame_t slot, int UE_id); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 99095e1dede3e0a64f6132b56e4c59f15862dd5a..4918e4ee0873460ffb06a20574253c3d5e037fb4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -717,7 +717,8 @@ typedef struct { // UE selected beam index uint8_t UE_beam_index[MAX_MOBILES_PER_GNB]; bool Msg4_ACKed[MAX_MOBILES_PER_GNB]; - + /// Sched CSI-RS: scheduling decisions + bool sched_csirs; } NR_UE_info_t; typedef void (*nr_pp_impl_dl)(module_id_t mod_id, @@ -814,15 +815,8 @@ typedef struct gNB_MAC_INST_s { /// bitmap of DLSCH slots, can hold up to 160 slots uint64_t dlsch_slot_bitmap[3]; - /// Lookup for preferred time domain allocation for BWP, in DL, slots - /// dynamically allocated - int *preferred_dl_tda[MAX_NUM_BWP]; /// bitmap of ULSCH slots, can hold up to 160 slots uint64_t ulsch_slot_bitmap[3]; - /// Lookup for preferred time domain allocation for UL BWP, dynamically - /// allocated. The index refers to the DL slot, and the indicated TDA's k2 - /// points to the right UL slot - int *preferred_ul_tda[MAX_NUM_BWP]; /// maximum number of slots before a UE will be scheduled ULSCH automatically uint32_t ulsch_max_frame_inactivity; diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index ef95443a5dc4e0a2bf9eb031fdf79a87d08f4794..e0f72fc4853efc8404f7e771c0f2a663d34d2a67 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -321,8 +321,7 @@ void nr_rrc_config_dl_tda(NR_ServingCellConfigCommon_t *scc, int len_coreset = 1; if (curr_bwp < 48) len_coreset = 2; - - // setting default TDA for DL with + // setting default TDA for DL with TDA index 0 struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); // k0: Slot offset between DCI and its scheduled PDSCH (see TS 38.214 clause 5.1.2.1) When the field is absent the UE applies the value 0. //timedomainresourceallocation->k0 = calloc(1,sizeof(*timedomainresourceallocation->k0)); @@ -330,18 +329,20 @@ void nr_rrc_config_dl_tda(NR_ServingCellConfigCommon_t *scc, timedomainresourceallocation->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; timedomainresourceallocation->startSymbolAndLength = get_SLIV(len_coreset,14-len_coreset); // basic slot configuration starting in symbol 1 til the end of the slot ASN_SEQUENCE_ADD(&pdsch_TimeDomainAllocationList->list, timedomainresourceallocation); + // setting TDA for CSI-RS symbol with index 1 + struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation1 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); + timedomainresourceallocation1->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; + timedomainresourceallocation1->startSymbolAndLength = get_SLIV(len_coreset,14-len_coreset-1); // 1 symbol CSI-RS + ASN_SEQUENCE_ADD(&pdsch_TimeDomainAllocationList->list, timedomainresourceallocation1); if(frame_type==TDD) { - // TDD if(scc->tdd_UL_DL_ConfigurationCommon) { int dl_symb = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols; if(dl_symb > 1) { - timedomainresourceallocation = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); - // k0: Slot offset between DCI and its scheduled PDSCH (see TS 38.214 clause 5.1.2.1) When the field is absent the UE applies the value 0. - //timedomainresourceallocation->k0 = calloc(1,sizeof(*timedomainresourceallocation->k0)); - //*timedomainresourceallocation->k0 = 0; - timedomainresourceallocation->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - timedomainresourceallocation->startSymbolAndLength = get_SLIV(len_coreset,dl_symb-len_coreset); // mixed slot configuration starting in symbol 1 til the end of the dl allocation - ASN_SEQUENCE_ADD(&pdsch_TimeDomainAllocationList->list, timedomainresourceallocation); + // mixed slot TDA with TDA index 2 + struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation2 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); + timedomainresourceallocation2->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; + timedomainresourceallocation2->startSymbolAndLength = get_SLIV(len_coreset,dl_symb-len_coreset); // mixed slot configuration starting in symbol 1 til the end of the dl allocation + ASN_SEQUENCE_ADD(&pdsch_TimeDomainAllocationList->list, timedomainresourceallocation2); } } } @@ -373,38 +374,40 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay){ uint8_t DELTA[4]= {2,3,4,6}; // Delta parameter for Msg3 int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + // UL TDA index 0 is basic slot configuration starting in symbol 0 til the last but one symbol struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long)); *pusch_timedomainresourceallocation->k2 = k2; pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(0,13); // basic slot configuration starting in symbol 0 til the last but one symbol + pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(0,13); ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation); if(frame_type==TDD) { - - // TDD if(scc->tdd_UL_DL_ConfigurationCommon) { int ul_symb = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; - pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long)); - *pusch_timedomainresourceallocation->k2 = k2; - pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(14-ul_symb,ul_symb-1); // starting in fist ul symbol til the last but one - ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation); - - // for msg3 in the mixed slot - int nb_periods_per_frame = get_nb_periods_per_frame(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity); - int nb_slots_per_period = ((1<<mu) * 10)/nb_periods_per_frame; - struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation_msg3 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation_msg3->k2 = CALLOC(1,sizeof(long)); - *pusch_timedomainresourceallocation_msg3->k2 = nb_slots_per_period - DELTA[mu]; - if(*pusch_timedomainresourceallocation_msg3->k2 < min_fb_delay) - *pusch_timedomainresourceallocation_msg3->k2 += nb_slots_per_period; - AssertFatal(*pusch_timedomainresourceallocation_msg3->k2<33,"Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n", - *pusch_timedomainresourceallocation_msg3->k2); - pusch_timedomainresourceallocation_msg3->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation_msg3->startSymbolAndLength = get_SLIV(14-ul_symb,ul_symb-1); // starting in fist ul symbol til the last but one - ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation_msg3); + if (ul_symb>1) { + // UL TDA index 1 for mixed slot (TDD) + pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); + pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long)); + *pusch_timedomainresourceallocation->k2 = k2; + pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; + pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(14-ul_symb,ul_symb-1); // starting in fist ul symbol til the last but one + ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation); + + // UL TDA index 2 for msg3 in the mixed slot (TDD) + int nb_periods_per_frame = get_nb_periods_per_frame(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity); + int nb_slots_per_period = ((1<<mu) * 10)/nb_periods_per_frame; + struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation_msg3 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); + pusch_timedomainresourceallocation_msg3->k2 = CALLOC(1,sizeof(long)); + *pusch_timedomainresourceallocation_msg3->k2 = nb_slots_per_period - DELTA[mu]; + if(*pusch_timedomainresourceallocation_msg3->k2 < min_fb_delay) + *pusch_timedomainresourceallocation_msg3->k2 += nb_slots_per_period; + AssertFatal(*pusch_timedomainresourceallocation_msg3->k2<33,"Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n", + *pusch_timedomainresourceallocation_msg3->k2); + pusch_timedomainresourceallocation_msg3->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; + pusch_timedomainresourceallocation_msg3->startSymbolAndLength = get_SLIV(14-ul_symb,ul_symb-1); // starting in fist ul symbol til the last but one + ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation_msg3); + } } } }