diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 61ff6b838f615a2231007913cb9243e706eaa92c..73593e4385285ac486a50e080d406f19e609bc51 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -411,8 +411,8 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // TODO // Schedule CSI measurement reporting: check in slot 0 for the whole frame - if (slot == 0 && UE_info->active[UE_id]) - nr_csi_meas_reporting(module_idP, UE_id, frame, slot); + if (slot == 0) + nr_csi_meas_reporting(module_idP, frame, slot); // This schedule RA procedure if not in phy_test mode // Otherwise already consider 5G already connected diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 570d14a95783e8be6d606b7d9aff56beef35180f..247d0e2a94ef422323f53152b63aec70b07e933e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -179,76 +179,103 @@ uint16_t nr_get_csi_bitlen(const nr_csi_report_t *csi_report) void nr_csi_meas_reporting(int Mod_idP, - int UE_id, frame_t frame, sub_frame_t slot) { - NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; - const NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id]; - NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - const NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; - AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count > 0, - "NO CSI report configuration available"); - NR_PUCCH_Config_t *pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup; - NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ - const NR_CSI_ReportConfig_t *csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; - - AssertFatal(csirep->reportConfigType.choice.periodic, - "Only periodic CSI reporting is implemented currently\n"); - int period, offset; - csi_period_offset(csirep, &period, &offset); - const int sched_slot = (period + offset) % n_slots_frame; - // 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) - continue; - LOG_D(MAC, "CSI in frame %d slot %d\n", frame, sched_slot); - - // we are scheduling pucch for csi in the first pucch occasion (this comes before ack/nack) - // FIXME: for the moment, we statically put it into the second sched_pucch! - NR_sched_pucch_t *curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[2]; - - const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0]; - const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1 - const int n = pucchresset->resourceList.list.count; - int res_index = 0; - for (; res_index < n; res_index++) - if (*pucchresset->resourceList.list.array[res_index] == pucchcsires->pucch_Resource) - break; - AssertFatal(res_index < n, - "CSI resource not found among PUCCH resources\n"); - curr_pucch->resource_indicator = res_index; - - // going through the list of PUCCH resources to find the one indexed by resource_id - const int m = pucch_Config->resourceToAddModList->list.count; - for (int j = 0; j < m; j++) { - NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[j]; - if (pucchres->pucch_ResourceId != *pucchresset->resourceList.list.array[res_index]) + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_UE_list_t *UE_list = &UE_info->list; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + const NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id]; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count > 0, + "NO CSI report configuration available"); + NR_PUCCH_Config_t *pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup; + + for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ + const NR_CSI_ReportConfig_t *csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; + + AssertFatal(csirep->reportConfigType.choice.periodic, + "Only periodic CSI reporting is implemented currently\n"); + int period, offset; + csi_period_offset(csirep, &period, &offset); + const int sched_slot = (period + offset) % n_slots_frame; + // 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) continue; - switch(pucchres->format.present){ - case NR_PUCCH_Resource__format_PR_format2: - curr_pucch->simultaneous_harqcsi = pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI; - break; - case NR_PUCCH_Resource__format_PR_format3: - curr_pucch->simultaneous_harqcsi = pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI; - break; - case NR_PUCCH_Resource__format_PR_format4: - curr_pucch->simultaneous_harqcsi = pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI; + LOG_D(MAC, "CSI in frame %d slot %d\n", frame, sched_slot); + + const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0]; + const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1 + const int n = pucchresset->resourceList.list.count; + int res_index = 0; + for (; res_index < n; res_index++) + if (*pucchresset->resourceList.list.array[res_index] == pucchcsires->pucch_Resource) break; - default: - AssertFatal(0, "Invalid PUCCH format type\n"); + AssertFatal(res_index < n, + "CSI resource not found among PUCCH resources\n"); + + // 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[2]; + AssertFatal(curr_pucch->csi_bits == 0 + && !curr_pucch->sr_flag + && curr_pucch->dai_c == 0, + "PUCCH not free at index 2 for UE %04x\n", + UE_info->rnti[UE_id]); + curr_pucch->frame = frame; + curr_pucch->ul_slot = sched_slot; + curr_pucch->resource_indicator = res_index; + curr_pucch->csi_bits += + nr_get_csi_bitlen(&UE_info->csi_report_template[UE_id][csi_report_id]); + + // going through the list of PUCCH resources to find the one indexed by resource_id + uint16_t *vrb_map_UL = &RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL[sched_slot * MAX_BWP_SIZE]; + const int m = pucch_Config->resourceToAddModList->list.count; + for (int j = 0; j < m; j++) { + NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[j]; + if (pucchres->pucch_ResourceId != *pucchresset->resourceList.list.array[res_index]) + continue; + int start = pucchres->startingPRB; + int len = 1; + uint64_t mask = 0; + switch(pucchres->format.present){ + case NR_PUCCH_Resource__format_PR_format2: + len = pucchres->format.choice.format2->nrofPRBs; + mask = ((1 << pucchres->format.choice.format2->nrofSymbols) - 1) << pucchres->format.choice.format2->startingSymbolIndex; + curr_pucch->simultaneous_harqcsi = pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI; + break; + case NR_PUCCH_Resource__format_PR_format3: + len = pucchres->format.choice.format3->nrofPRBs; + mask = ((1 << pucchres->format.choice.format3->nrofSymbols) - 1) << pucchres->format.choice.format3->startingSymbolIndex; + curr_pucch->simultaneous_harqcsi = pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI; + break; + case NR_PUCCH_Resource__format_PR_format4: + mask = ((1 << pucchres->format.choice.format4->nrofSymbols) - 1) << pucchres->format.choice.format4->startingSymbolIndex; + curr_pucch->simultaneous_harqcsi = pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI; + break; + default: + AssertFatal(0, "Invalid PUCCH format type\n"); + } + // verify resources are free + for (int i = start; i < start + len; ++i) { + AssertFatal((vrb_map_UL[i] & mask) == 0, + "cannot allocate CSI PUCCH for UE %04x: PRB %d used in symbs %lx\n", + UE_info->rnti[UE_id], + i, + mask); + vrb_map_UL[i] |= mask; + } + AssertFatal(!curr_pucch->simultaneous_harqcsi, + "UE %04x has simultaneous HARQ/CSI configured, but we don't support that\n", + UE_info->rnti[UE_id]); } } - - curr_pucch->csi_bits += - nr_get_csi_bitlen(&UE_info->csi_report_template[UE_id][csi_report_id]); - curr_pucch->frame = frame; - curr_pucch->ul_slot = sched_slot; } } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index f084ea974baaabff3b39dd8be1eec3951bd10ebe..db3d8aab69660ebde5e21bc1ebc0b46d863ad1e2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -217,7 +217,6 @@ void csi_period_offset(const NR_CSI_ReportConfig_t *csirep, int *period, int *offset); void nr_csi_meas_reporting(int Mod_idP, - int UE_id, frame_t frameP, sub_frame_t slotP);