diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index ba29a2176b41582203f8a43b24560c83fcce20d8..8145cf893c47103803c97b56cd6f4d612a271db5 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -1621,7 +1621,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, if (pucch_pdu->bit_len_harq>0) { int harq_bytes=pucch_pdu->bit_len_harq>>3; if ((pucch_pdu->bit_len_harq&7) > 0) harq_bytes++; - uci_pdu->pduBitmap|=1; + uci_pdu->pduBitmap|=2; uci_pdu->harq.harq_payload = (uint8_t*)malloc(harq_bytes); uci_pdu->harq.harq_crc = decoderState; int i=0; @@ -1635,7 +1635,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, } if (pucch_pdu->sr_flag == 1) { - uci_pdu->pduBitmap|=2; + uci_pdu->pduBitmap|=1; uci_pdu->sr.sr_bit_len = 1; uci_pdu->sr.sr_payload = malloc(1); uci_pdu->sr.sr_payload[0] = decodedPayload[0]&1; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index a4c80262e89c3cb0656b26a1c53ad42218a5bc01..7c1cbea9b649cedebf5301c4d1088d1b5ff32c37 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1172,9 +1172,11 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra harq->is_waiting = true; ra->harq_pid = current_harq_pid; - nr_acknack_scheduling(module_idP, UE_id, frameP, slotP); - harq->feedback_slot = sched_ctrl->sched_pucch->ul_slot; - harq->feedback_frame = sched_ctrl->sched_pucch->frame; + int alloc = nr_acknack_scheduling(module_idP, UE_id, frameP, slotP); + AssertFatal(alloc>=0,"Couldn't find a pucch allocation for ack nack (msg4)\n"); + NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[alloc]; + harq->feedback_slot = pucch->ul_slot; + harq->feedback_frame = pucch->frame; // Bytes to be transmitted uint8_t *buf = (uint8_t *) harq->tb; @@ -1376,10 +1378,10 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra dci_payload.rv = pdsch_pdu_rel15->rvIndex[0]; dci_payload.harq_pid = current_harq_pid; dci_payload.ndi = harq->ndi; - dci_payload.dai[0].val = (sched_ctrl->sched_pucch->dai_c-1)&3; + dci_payload.dai[0].val = (pucch->dai_c-1)&3; dci_payload.tpc = sched_ctrl->tpc1; // TPC for PUCCH: table 7.2.1-1 in 38.213 - dci_payload.pucch_resource_indicator = sched_ctrl->sched_pucch->resource_indicator; - dci_payload.pdsch_to_harq_feedback_timing_indicator.val = sched_ctrl->sched_pucch->timing_indicator; + dci_payload.pucch_resource_indicator = pucch->resource_indicator; + dci_payload.pdsch_to_harq_feedback_timing_indicator.val = pucch->timing_indicator; LOG_D(NR_MAC, "[RAPROC] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d \n", diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index e17fb5e34674909e89b7a5808ef3b43a6a790cbb..cb1a73edae5735f9bc83164e8101311662288faf 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -492,8 +492,8 @@ bool allocate_dl_retransmission(module_id_t module_id, /* Find PUCCH occasion: if it fails, undo CCE allocation (undoing PUCCH * allocation after CCE alloc fail would be more complex) */ - const bool alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot); - if (!alloc) { + const int alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot); + if (alloc<0) { LOG_D(MAC, "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n", __func__, @@ -509,6 +509,8 @@ bool allocate_dl_retransmission(module_id_t module_id, return false; } + sched_ctrl->sched_pdsch.pucch_allocation = alloc; + /* just reuse from previous scheduling opportunity, set new start RB */ sched_ctrl->sched_pdsch = *retInfo; sched_ctrl->sched_pdsch.rbStart = rbStart; @@ -615,8 +617,8 @@ void pf_dl(module_id_t module_id, /* Find PUCCH occasion: if it fails, undo CCE allocation (undoing PUCCH * allocation after CCE alloc fail would be more complex) */ - const bool alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot); - if (!alloc) { + const int alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot); + if (alloc<0) { LOG_D(MAC, "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n", __func__, @@ -648,7 +650,7 @@ void pf_dl(module_id_t module_id, scc, UE_info->secondaryCellGroup[UE_id], sched_ctrl->active_bwp, tda, num_dmrs_cdm_grps_no_data, ps); sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx); sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx); - + sched_pdsch->pucch_allocation = alloc; uint32_t TBS = 0; uint16_t rbSize; const int oh = 2 + (sched_ctrl->num_total_bytes >= 256) @@ -811,7 +813,7 @@ void nr_schedule_ue_spec(module_id_t module_id, NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; DevAssert(!harq->is_waiting); add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid); - NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0]; + NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[sched_pdsch->pucch_allocation]; harq->feedback_frame = pucch->frame; harq->feedback_slot = pucch->ul_slot; harq->is_waiting = true; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 616de10b619ab33db167601de8cbbcb5bd220d7f..adfcd79b8e68c88686aba69e23ed8f2f94cf0f3e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -339,8 +339,8 @@ void nr_preprocessor_phytest(module_id_t module_id, __func__, UE_id); - const bool alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot); - if (!alloc) { + const int alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot); + if (alloc < 0) { LOG_D(MAC, "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n", __func__, @@ -355,12 +355,13 @@ void nr_preprocessor_phytest(module_id_t module_id, return; } - AssertFatal(alloc, - "could not find uplink slot for PUCCH (RNTI %04x@%d.%d)!\n", - rnti, frame, slot); + //AssertFatal(alloc, + // "could not find uplink slot for PUCCH (RNTI %04x@%d.%d)!\n", + // rnti, frame, slot); NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; + sched_pdsch->pucch_allocation = alloc; sched_pdsch->rbStart = rbStart; sched_pdsch->rbSize = rbSize; const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp->bwp_Id][slot]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 800c23a9a0b318afa2fcb2fc6e34648bd8e66de9..f53f79ba499c661f840b40909b9ce1b4086149df 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -553,9 +553,6 @@ void nr_csi_meas_reporting(int Mod_idP, for (int i = start; i < start + len; ++i) { 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]); } } } @@ -1088,10 +1085,14 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, // function to update pucch scheduling parameters in UE list when a USS DL is scheduled -bool nr_acknack_scheduling(int mod_id, - int UE_id, - frame_t frame, - sub_frame_t slot) +// 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, + int UE_id, + frame_t frame, + sub_frame_t slot) { const NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; @@ -1101,6 +1102,7 @@ bool nr_acknack_scheduling(int mod_id, const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots; const int first_ul_slot_tdd = tdd->nrofDownlinkSlots + nr_slots_period * (slot / nr_slots_period); const int CC_id = 0; + NR_sched_pucch_t *csi_pucch; AssertFatal(slot < first_ul_slot_tdd + (tdd->nrofUplinkSymbols != 0), "cannot handle multiple TDD periods (yet): slot %d first_ul_slot_tdd %d nrofUplinkSlots %ld\n", @@ -1120,7 +1122,6 @@ bool nr_acknack_scheduling(int mod_id, "%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 */ if (pucch->dai_c == 2) { /* advance the UL slot information in PUCCH by one so we won't schedule in @@ -1132,17 +1133,13 @@ bool nr_acknack_scheduling(int mod_id, pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; pucch->ul_slot = (s + 1) % n_slots_frame; // we assume that only two indices over the array sched_pucch exist - NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[1]; + csi_pucch = &sched_ctrl->sched_pucch[1]; // skip the CSI PUCCH if it is present and if in the next frame/slot + // and if we don't multiplex if (csi_pucch->csi_bits > 0 && csi_pucch->frame == pucch->frame - && csi_pucch->ul_slot == pucch->ul_slot) { - AssertFatal(!csi_pucch->simultaneous_harqcsi, - "%s(): %d.%d cannot handle simultaneous_harqcsi, but found for UE %d\n", - __func__, - pucch->frame, - pucch->ul_slot, - UE_id); + && csi_pucch->ul_slot == pucch->ul_slot + && !csi_pucch->simultaneous_harqcsi) { nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id); memset(csi_pucch, 0, sizeof(*csi_pucch)); pucch->frame = s >= n_slots_frame - 2 ? (f + 1) % 1024 : f; @@ -1156,7 +1153,7 @@ bool nr_acknack_scheduling(int mod_id, if ((pucch->frame == frame && (pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots)) || (pucch->frame == frame + 1)) - return false; + return -1; // this is hardcoded for now as ue specific NR_SearchSpace__searchSpaceType_PR ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific; @@ -1190,7 +1187,7 @@ bool nr_acknack_scheduling(int mod_id, pucch->timing_indicator = i; pucch->dai_c++; // retain old resource indicator, and we are good - return true; + return 0; } /* we need to find a new PUCCH occasion */ @@ -1213,30 +1210,6 @@ bool nr_acknack_scheduling(int mod_id, // advance ul_slot if it is not reachable by UE pucch->ul_slot = max(pucch->ul_slot, slot + pdsch_to_harq_feedback[0]); - // is there already CSI in this slot? - NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[1]; - // skip the CSI PUCCH if it is present and if in the next frame/slot - if (csi_pucch->csi_bits > 0 - && csi_pucch->frame == pucch->frame - && csi_pucch->ul_slot == pucch->ul_slot) { - AssertFatal(!csi_pucch->simultaneous_harqcsi, - "%s(): %d.%d cannot handle simultaneous_harqcsi, but found for UE %d\n", - __func__, - pucch->frame, - pucch->ul_slot, - UE_id); - nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id); - 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; - pucch->ul_slot = (s + 1) % n_slots_frame; - return nr_acknack_scheduling(mod_id, UE_id, frame, slot); - } - // Find the right timing_indicator value. int i = 0; while (i < 8) { @@ -1252,8 +1225,38 @@ bool nr_acknack_scheduling(int mod_id, slot, UE_id, pucch->ul_slot); - return false; + return -1; + } + + // is there already CSI in this slot? + csi_pucch = &sched_ctrl->sched_pucch[1]; + if (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 + if(!csi_pucch->simultaneous_harqcsi + || ((csi_pucch->csi_bits + csi_pucch->dai_c) >= 11)) { + nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id); + 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; + pucch->ul_slot = (s + 1) % n_slots_frame; + return nr_acknack_scheduling(mod_id, UE_id, frame, slot); + } + // multiplexing harq and csi in a pucch + else { + csi_pucch->timing_indicator = i; + csi_pucch->dai_c++; + return 1; + } } + pucch->timing_indicator = i; // index in the list of timing indicators pucch->dai_c++; @@ -1272,7 +1275,7 @@ bool nr_acknack_scheduling(int mod_id, LOG_W(MAC, "symbol 0x%x is not free for PUCCH alloc in vrb_map_UL at RB %ld and slot %d.%d\n", symb, resource->startingPRB, pucch->frame, pucch->ul_slot); vrb_map_UL[resource->startingPRB] |= symb; } - return true; + return 0; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 4bf82dd002821e27795d499fc7aced3635809594..1010ebafda335f12bfb37cd164ee0fc5de610418 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -186,10 +186,10 @@ void nr_csi_meas_reporting(int Mod_idP, frame_t frameP, sub_frame_t slotP); -bool nr_acknack_scheduling(int Mod_idP, - int UE_id, - frame_t frameP, - sub_frame_t slotP); +int nr_acknack_scheduling(int Mod_idP, + int UE_id, + frame_t frameP, + sub_frame_t slotP); void get_pdsch_to_harq_feedback(int Mod_idP, 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 52255b8f3226dc3d78bb9d1f0790111656815be3..c1ec27580f9bc7b31178cc5d5a13902a81b6308c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -389,6 +389,9 @@ typedef struct NR_sched_pdsch { /// DL HARQ PID to use for this UE, or -1 for "any new" int8_t dl_harq_pid; + // pucch format allocation + uint8_t pucch_allocation; + /// the Time Domain Allocation used for this transmission. Note that this is /// only important for retransmissions; otherwise, the TDA in /// NR_pdsch_semi_static_t has precedence diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index 7788066dd33b3c6ade7a9368a36641041afa8d61..8ed19e9d82979f2619f6c74c261563fd0812ce20 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -1009,10 +1009,11 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco pucchfmt2->interslotFrequencyHopping=NULL; pucchfmt2->additionalDMRS=NULL; pucchfmt2->maxCodeRate=calloc(1,sizeof(*pucchfmt2->maxCodeRate)); - *pucchfmt2->maxCodeRate=NR_PUCCH_MaxCodeRate_zeroDot25; + *pucchfmt2->maxCodeRate=NR_PUCCH_MaxCodeRate_zeroDot35; pucchfmt2->nrofSlots=NULL; pucchfmt2->pi2BPSK=NULL; - pucchfmt2->simultaneousHARQ_ACK_CSI=NULL; + pucchfmt2->simultaneousHARQ_ACK_CSI=calloc(1,sizeof(*pucchfmt2->simultaneousHARQ_ACK_CSI)); + *pucchfmt2->simultaneousHARQ_ACK_CSI=NR_PUCCH_FormatConfig__simultaneousHARQ_ACK_CSI_true; // for scheduling requestresource pucch_Config->schedulingRequestResourceToAddModList = calloc(1,sizeof(*pucch_Config->schedulingRequestResourceToAddModList));