From 517d3514300a13342f386470fc7e3a4a704ade87 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 21 Aug 2023 14:25:11 +0200 Subject: [PATCH] adding a test on max number of bits to be scheduled on pucch according to coderate --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 49 +++++-- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 3 + .../NR_MAC_gNB/gNB_scheduler_primitives.c | 100 +++++--------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 122 +++++++++++++++++- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 + 5 files changed, 189 insertions(+), 87 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 0067c546ba..5e42abd3bb 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -4642,17 +4642,8 @@ int compute_pucch_crc_size(int O_uci) } } -uint16_t compute_pucch_prb_size(uint8_t format, - uint8_t nr_prbs, - uint16_t O_uci, - NR_PUCCH_MaxCodeRate_t *maxCodeRate, - uint8_t Qm, - uint8_t n_symb, - uint8_t n_re_ctrl) +float get_max_code_rate(NR_PUCCH_MaxCodeRate_t *maxCodeRate) { - int O_crc = compute_pucch_crc_size(O_uci); - int O_tot = O_uci + O_crc; - int rtimes100; switch(*maxCodeRate){ case NR_PUCCH_MaxCodeRate_zeroDot08 : @@ -4680,12 +4671,46 @@ uint16_t compute_pucch_prb_size(uint8_t format, AssertFatal(1==0,"Invalid MaxCodeRate"); } - float r = (float)rtimes100/100; + float r = (float)rtimes100 / 100; + return r; +} + +int get_f3_dmrs_symbols(NR_PUCCH_Resource_t *pucchres, NR_PUCCH_Config_t *pucch_Config) +{ + int f3_dmrs_symbols; + int add_dmrs_flag; + if (pucch_Config->format3 == NULL) + add_dmrs_flag = 0; + else + add_dmrs_flag = pucch_Config->format3->choice.setup->additionalDMRS ? 1 : 0; + if (pucchres->format.choice.format3->nrofSymbols == 4) + f3_dmrs_symbols = 1 << (pucchres->intraSlotFrequencyHopping ? 1 : 0); + else { + if (pucchres->format.choice.format3->nrofSymbols < 10) + f3_dmrs_symbols = 2; + else + f3_dmrs_symbols = 2 << add_dmrs_flag; + } + return f3_dmrs_symbols; +} + +uint16_t compute_pucch_prb_size(uint8_t format, + uint8_t nr_prbs, + uint16_t O_uci, + NR_PUCCH_MaxCodeRate_t *maxCodeRate, + uint8_t Qm, + uint8_t n_symb, + uint8_t n_re_ctrl) +{ + int O_crc = compute_pucch_crc_size(O_uci); + int O_tot = O_uci + O_crc; + + float r = get_max_code_rate(maxCodeRate); AssertFatal(O_tot <= (nr_prbs * n_re_ctrl * n_symb * Qm * r), "MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with %d PRBs", r, - O_tot, + O_uci, O_crc, nr_prbs); diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 07daa61725..ab7a820612 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -244,6 +244,9 @@ uint16_t compute_pucch_prb_size(uint8_t format, uint8_t n_symb, uint8_t n_re_ctrl); +float get_max_code_rate(NR_PUCCH_MaxCodeRate_t *maxCodeRate); +int get_f3_dmrs_symbols(NR_PUCCH_Resource_t *pucchres, NR_PUCCH_Config_t *pucch_Config); + int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH); void find_period_offset_SR(const NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 81ea2edcb7..3983773c56 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -812,23 +812,19 @@ int nr_get_pucch_resource(NR_ControlResourceSet_t *coreset, } // This function configures pucch pdu fapi structure -void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, +void nr_configure_pucch(nfapi_nr_pucch_pdu_t *pucch_pdu, NR_ServingCellConfigCommon_t *scc, NR_UE_info_t *UE, uint8_t pucch_resource, uint16_t O_csi, uint16_t O_ack, uint8_t O_sr, - int r_pucch) { - + int r_pucch) +{ NR_PUCCH_Resource_t *pucchres; - NR_PUCCH_ResourceSet_t *pucchresset; NR_PUCCH_FormatConfig_t *pucchfmt; - NR_PUCCH_ResourceId_t *resource_id = NULL; NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP; - int n_list, n_set; - uint16_t N2,N3; int res_found = 0; pucch_pdu->bit_len_harq = O_ack; @@ -884,60 +880,27 @@ 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) { - LOG_D(NR_MAC,"pucch_acknak: Filling dedicated configuration for PUCCH\n"); + if (r_pucch < 0 || pucch_Config) { + LOG_D(NR_MAC, "pucch_acknak: Filling dedicated configuration for PUCCH\n"); - AssertFatal(pucch_Config->resourceSetToAddModList!=NULL, - "PUCCH resourceSetToAddModList is null\n"); - - n_set = pucch_Config->resourceSetToAddModList->list.count; - AssertFatal(n_set>0,"PUCCH resourceSetToAddModList is empty\n"); - - LOG_D(NR_MAC, "UCI n_set= %d\n", n_set); - - N2 = 2; - // procedure to select pucch resource id from resource sets according to - // number of uci bits and pucch resource indicator pucch_resource - // ( see table 9.2.3.2 in 38.213) - for (int i=0; iresourceSetToAddModList->list.array[i]; - n_list = pucchresset->resourceList.list.count; - if (pucchresset->pucch_ResourceSetId == 0 && O_uci<3) { - if (pucch_resource < n_list) - resource_id = pucchresset->resourceList.list.array[pucch_resource]; - else - AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci); - } - if (pucchresset->pucch_ResourceSetId == 1 && O_uci>2) { - N3 = pucchresset->maxPayloadSize!= NULL ? *pucchresset->maxPayloadSize : 1706; - if (N2O_uci) { - if (pucch_resource < n_list) - resource_id = pucchresset->resourceList.list.array[pucch_resource]; - else - AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci); - } - else N2 = N3; - } - } - - AssertFatal(resource_id!=NULL,"Couldn-t find any matching PUCCH resource in the PUCCH resource sets"); + int resource_id = get_pucch_resourceid(pucch_Config, O_uci, pucch_resource); AssertFatal(pucch_Config->resourceToAddModList!=NULL, "PUCCH resourceToAddModList is null\n"); - n_list = pucch_Config->resourceToAddModList->list.count; - AssertFatal(n_list>0,"PUCCH resourceToAddModList is empty\n"); + int n_list = pucch_Config->resourceToAddModList->list.count; + AssertFatal(n_list > 0, "PUCCH resourceToAddModList is empty\n"); // going through the list of PUCCH resources to find the one indexed by resource_id - for (int i=0; iresourceToAddModList->list.array[i]; - if (pucchres->pucch_ResourceId == *resource_id) { + if (pucchres->pucch_ResourceId == resource_id) { res_found = 1; pucch_pdu->prb_start = pucchres->startingPRB; pucch_pdu->rnti = UE->rnti; // FIXME why there is only one frequency hopping flag // what about inter slot frequency hopping? - pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping!= NULL ? 1 : 0; + pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping ? 1 : 0; pucch_pdu->second_hop_prb = pucchres->secondHopPRB!= NULL ? *pucchres->secondHopPRB : 0; switch(pucchres->format.present) { case NR_PUCCH_Resource__format_PR_format0 : @@ -962,8 +925,8 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, 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; - pucch_pdu->dmrs_scrambling_id = id0!= NULL ? *id0 : *scc->physCellId; + pucch_pdu->data_scrambling_id = pusch_id ? *pusch_id : *scc->physCellId; + pucch_pdu->dmrs_scrambling_id = id0 ? *id0 : *scc->physCellId; pucch_pdu->prb_size = compute_pucch_prb_size(2, pucchres->format.choice.format2->nrofPRBs, O_uci + O_sr, @@ -977,25 +940,17 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, pucch_pdu->format_type = 3; pucch_pdu->nr_of_symbols = pucchres->format.choice.format3->nrofSymbols; pucch_pdu->start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex; - pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId; + pucch_pdu->data_scrambling_id = pusch_id ? *pusch_id : *scc->physCellId; if (pucch_Config->format3 == NULL) { pucch_pdu->pi_2bpsk = 0; pucch_pdu->add_dmrs_flag = 0; } else { pucchfmt = pucch_Config->format3->choice.setup; - pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0; - pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0; - } - int f3_dmrs_symbols; - if (pucchres->format.choice.format3->nrofSymbols==4) - f3_dmrs_symbols = 1<freq_hop_flag; - else { - if(pucchres->format.choice.format3->nrofSymbols<10) - f3_dmrs_symbols = 2; - else - f3_dmrs_symbols = 2<add_dmrs_flag; + pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK ? 1 : 0; + pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS ? 1 : 0; } + int f3_dmrs_symbols = get_f3_dmrs_symbols(pucchres, pucch_Config); pucch_pdu->prb_size = compute_pucch_prb_size(3, pucchres->format.choice.format3->nrofPRBs, O_uci + O_sr, @@ -1018,8 +973,8 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, } else { pucchfmt = pucch_Config->format3->choice.setup; - pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0; - pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0; + pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK != NULL; + pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS != NULL; } pucch_pdu->bit_len_csi_part1 = O_csi; break; @@ -1028,11 +983,17 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, } } } - AssertFatal(res_found==1,"No PUCCH resource found corresponding to id %ld\n",*resource_id); - LOG_D(NR_MAC,"Configure pucch: pucch_pdu->format_type %d pucch_pdu->bit_len_harq %d, pucch->pdu->bit_len_csi %d\n",pucch_pdu->format_type,pucch_pdu->bit_len_harq,pucch_pdu->bit_len_csi_part1); - } - else { // this is the default PUCCH configuration, PUCCH format 0 or 1 - LOG_D(NR_MAC,"pucch_acknak: Filling default PUCCH configuration from Tables (r_pucch %d, pucch_Config %p)\n",r_pucch,pucch_Config); + AssertFatal(res_found == 1, "No PUCCH resource found corresponding to id %d\n", resource_id); + LOG_D(NR_MAC, + "Configure pucch: pucch_pdu->format_type %d pucch_pdu->bit_len_harq %d, pucch->pdu->bit_len_csi %d\n", + pucch_pdu->format_type, + pucch_pdu->bit_len_harq, + pucch_pdu->bit_len_csi_part1); + } else { // this is the default PUCCH configuration, PUCCH format 0 or 1 + LOG_D(NR_MAC, + "pucch_acknak: Filling default PUCCH configuration from Tables (r_pucch %d, pucch_Config %p)\n", + r_pucch, + pucch_Config); int rsetindex = *pucch_ConfigCommon->pucch_ResourceCommon; int prb_start, second_hop_prb, nr_of_symb, start_symb; set_r_pucch_parms(rsetindex, @@ -1060,7 +1021,6 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, } } - void set_r_pucch_parms(int rsetindex, int r_pucch, int bwp_size, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index cf6001626d..1f04596fa7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -234,7 +234,7 @@ void nr_csi_meas_reporting(int Mod_idP, 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 - if ((sched_frame*n_slots_frame + sched_slot - offset)%period != 0) + if ((sched_frame * n_slots_frame + sched_slot - offset) % period != 0) continue; AssertFatal(is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[sched_slot / 64], sched_slot), "CSI reporting slot %d is not set for an uplink slot\n", sched_slot); @@ -280,7 +280,14 @@ 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", sched_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; @@ -297,7 +304,12 @@ 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, sched_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 @@ -308,6 +320,52 @@ void nr_csi_meas_reporting(int Mod_idP, } } +int get_pucch_resourceid(NR_PUCCH_Config_t *pucch_Config, int O_uci, int pucch_resource) +{ + NR_PUCCH_ResourceId_t *resource_id = NULL; + AssertFatal(pucch_Config->resourceSetToAddModList != NULL, "PUCCH resourceSetToAddModList is null\n"); + + int n_set = pucch_Config->resourceSetToAddModList->list.count; + AssertFatal(n_set > 0, "PUCCH resourceSetToAddModList is empty\n"); + + LOG_D(NR_MAC, "UCI n_set= %d\n", n_set); + + int N2 = 2; + // procedure to select pucch resource id from resource sets according to + // number of uci bits and pucch resource indicator pucch_resource + // ( see table 9.2.3.2 in 38.213) + for (int i = 0; i < n_set; i++) { + NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[i]; + int n_list = pucchresset->resourceList.list.count; + if (pucchresset->pucch_ResourceSetId == 0 && O_uci < 3) { + if (pucch_resource < n_list) + resource_id = pucchresset->resourceList.list.array[pucch_resource]; + else + AssertFatal(1 == 0, + "Couldn't find pucch resource indicator %d in PUCCH resource set %d for %d UCI bits", + pucch_resource, + i, + O_uci); + } + if (pucchresset->pucch_ResourceSetId == 1 && O_uci > 2) { + int N3 = pucchresset->maxPayloadSize != NULL ? *pucchresset->maxPayloadSize : 1706; + if (N2 < O_uci && N3 > O_uci) { + if (pucch_resource < n_list) + resource_id = pucchresset->resourceList.list.array[pucch_resource]; + else + AssertFatal(1 == 0, + "Couldn't find pucch resource indicator %d in PUCCH resource set %d for %d UCI bits", + pucch_resource, + i, + O_uci); + } else + N2 = N3; + } + } + AssertFatal(resource_id != NULL, "Couldn't find any matching PUCCH resource in the PUCCH resource sets"); + return *resource_id; +} + static void handle_dl_harq(NR_UE_info_t * UE, int8_t harq_pid, bool success, @@ -1094,6 +1152,51 @@ static void set_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, uint16_t *v } } +bool check_bits_vs_coderate_limit(NR_PUCCH_Config_t *pucch_Config, int O_uci, int pucch_resource) +{ + int resource_id = get_pucch_resourceid(pucch_Config, O_uci, pucch_resource); + AssertFatal(pucch_Config->resourceToAddModList != NULL, "PUCCH resourceToAddModList is null\n"); + + int n_list = pucch_Config->resourceToAddModList->list.count; + AssertFatal(n_list > 0, "PUCCH resourceToAddModList is empty\n"); + + // going through the list of PUCCH resources to find the one indexed by resource_id + for (int i = 0; i < n_list; i++) { + NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[i]; + if (pucchres->pucch_ResourceId == resource_id) { + NR_PUCCH_MaxCodeRate_t *maxCodeRate = NULL; + int nb_symbols = 0; + int prbs = 0; + int n_re_ctrl = 0; + int Qm = 0; + switch (pucchres->format.present) { + case NR_PUCCH_Resource__format_PR_format2: + prbs = pucchres->format.choice.format2->nrofPRBs; + maxCodeRate = pucch_Config->format2->choice.setup->maxCodeRate; + nb_symbols = pucchres->format.choice.format2->nrofSymbols; + n_re_ctrl = 8; + Qm = 2; + break; + case NR_PUCCH_Resource__format_PR_format3: + prbs = pucchres->format.choice.format3->nrofPRBs; + maxCodeRate = pucch_Config->format3->choice.setup->maxCodeRate; + int f3_dmrs_symbols = get_f3_dmrs_symbols(pucchres, pucch_Config); + nb_symbols = pucchres->format.choice.format3->nrofSymbols - f3_dmrs_symbols; + n_re_ctrl = 12; + Qm = pucch_Config->format3 ? (pucch_Config->format3->choice.setup->pi2BPSK ? 1 : 2) : 2; + break; + default: + AssertFatal(false, "PUCCH format %d not handled\n", pucchres->format.present); + } + int O_crc = compute_pucch_crc_size(O_uci); + int O_tot = O_uci + O_crc; + float r = get_max_code_rate(maxCodeRate); + return (O_tot <= (prbs * n_re_ctrl * nb_symbols * Qm * r)); + } + } + AssertFatal(false, "No PUCCH resource found\n"); +} + // 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(gNB_MAC_INST *mac, @@ -1151,8 +1254,17 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, curr_pucch->dai_c == 2) continue; // if there is CSI but simultaneous HARQ+CSI is disable we can't schedule - if(curr_pucch->csi_bits > 0 && - !curr_pucch->simultaneous_harqcsi) + if (curr_pucch->csi_bits > 0 && !curr_pucch->simultaneous_harqcsi) + continue; + // check if the number of bits to be scheduled can fit in current PUCCH + // according to PUCCH code rate (if not we search for another allocation) + // the number of bits in the check need to include possible SR (1 bit) + // and the ack/nack bit to be scheduled (1 bit) + // so the number of bits already scheduled in current pucch + 2 + if (curr_pucch->csi_bits > 0 + && !check_bits_vs_coderate_limit(pucch_Config, + curr_pucch->csi_bits + curr_pucch->dai_c + 2, + curr_pucch->resource_indicator)) continue; // otherwise we can schedule in this active PUCCH diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 10ba95928d..073da246f1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -170,6 +170,8 @@ void nr_srs_ri_computation(const nfapi_nr_srs_normalized_channel_iq_matrix_t *nr const NR_UE_UL_BWP_t *current_BWP, uint8_t *ul_ri); +int get_pucch_resourceid(NR_PUCCH_Config_t *pucch_Config, int O_uci, int pucch_resource); + void nr_schedule_srs(int module_id, frame_t frame, int slot); void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slots_frame, nfapi_nr_dl_tti_request_t *DL_req);