Merge remote-tracking branch 'origin/NR_MAC_PUCCH_rework' into integration_2022_wk43
This commit is contained in:
@@ -1536,12 +1536,6 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
|
|||||||
corr32_im[symb][group][aa]+((int16_t*)(&prod_im[aa]))[0]);
|
corr32_im[symb][group][aa]+((int16_t*)(&prod_im[aa]))[0]);
|
||||||
|
|
||||||
#endif
|
#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_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]);
|
corr_im = ( corr32_im[symb][group][aa]+((int16_t*)(&prod_im[aa]))[0]);
|
||||||
|
|||||||
@@ -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;
|
NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR P_O = SchedulingReqRec->periodicityAndOffset->present;
|
||||||
switch (P_O){
|
switch (P_O){
|
||||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl1:
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl1:
|
||||||
|
|||||||
@@ -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);
|
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,
|
void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
|
||||||
struct NR_CSI_ResourcePeriodicityAndOffset *periodicityAndOffset,
|
struct NR_CSI_ResourcePeriodicityAndOffset *periodicityAndOffset,
|
||||||
|
|||||||
@@ -2389,7 +2389,7 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac,
|
|||||||
NR_SchedulingRequestResourceConfig_t *SchedulingRequestResourceConfig = pucch_Config->schedulingRequestResourceToAddModList->list.array[SR_resource_id];
|
NR_SchedulingRequestResourceConfig_t *SchedulingRequestResourceConfig = pucch_Config->schedulingRequestResourceToAddModList->list.array[SR_resource_id];
|
||||||
int SR_period; int SR_offset;
|
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;
|
int sfn_sf = frame * n_slots_frame + slot;
|
||||||
|
|
||||||
if ((sfn_sf - SR_offset) % SR_period == 0) {
|
if ((sfn_sf - SR_offset) % SR_period == 0) {
|
||||||
|
|||||||
@@ -215,9 +215,8 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
|||||||
// Schedule CSI-RS transmission
|
// Schedule CSI-RS transmission
|
||||||
nr_csirs_scheduling(module_idP, frame, slot, nr_slots_per_frame[*scc->ssbSubcarrierSpacing]);
|
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
|
// Schedule CSI measurement reporting
|
||||||
if (slot == 0)
|
nr_csi_meas_reporting(module_idP, frame, slot);
|
||||||
nr_csi_meas_reporting(module_idP, frame, slot);
|
|
||||||
|
|
||||||
// Schedule SRS: check in slot 0 for the whole frame
|
// Schedule SRS: check in slot 0 for the whole frame
|
||||||
if (slot == 0)
|
if (slot == 0)
|
||||||
@@ -237,11 +236,10 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
|||||||
nr_schedule_ue_spec(module_idP, frame, slot);
|
nr_schedule_ue_spec(module_idP, frame, slot);
|
||||||
stop_meas(&gNB->schedule_dlsch);
|
stop_meas(&gNB->schedule_dlsch);
|
||||||
|
|
||||||
nr_schedule_pucch(RC.nrmac[module_idP], frame, slot);
|
|
||||||
|
|
||||||
// This schedule SR after PUCCH for multiplexing
|
|
||||||
nr_sr_reporting(RC.nrmac[module_idP], frame, slot);
|
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);
|
stop_meas(&RC.nrmac[module_idP]->eNB_scheduler);
|
||||||
|
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT);
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT);
|
||||||
|
|||||||
@@ -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);
|
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) {
|
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);
|
LOG_D(NR_MAC,"Couldn't find a pucch allocation for ack nack (msg4) in frame %d slot %d\n",frameP,slotP);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -508,7 +508,7 @@ bool allocate_dl_retransmission(module_id_t module_id,
|
|||||||
* allocation after CCE alloc fail would be more complex) */
|
* allocation after CCE alloc fail would be more complex) */
|
||||||
|
|
||||||
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, ul_bwp->pucch_Config, CCEIndex);
|
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) {
|
if (alloc<0) {
|
||||||
LOG_D(MAC,
|
LOG_D(MAC,
|
||||||
"could not find PUCCH for UE %04x@%d.%d\n",
|
"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) */
|
* allocation after CCE alloc fail would be more complex) */
|
||||||
|
|
||||||
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, ul_bwp->pucch_Config, CCEIndex);
|
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) {
|
if (alloc<0) {
|
||||||
LOG_D(NR_MAC,
|
LOG_D(NR_MAC,
|
||||||
|
|||||||
@@ -277,7 +277,7 @@ void nr_preprocessor_phytest(module_id_t module_id,
|
|||||||
UE->rnti);
|
UE->rnti);
|
||||||
|
|
||||||
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, UE->current_UL_BWP.pucch_Config, CCEIndex);
|
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) {
|
if (alloc < 0) {
|
||||||
LOG_D(MAC,
|
LOG_D(MAC,
|
||||||
"%s(): could not find PUCCH for UE %04x@%d.%d\n",
|
"%s(): could not find PUCCH for UE %04x@%d.%d\n",
|
||||||
|
|||||||
@@ -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;
|
pucch_pdu->cyclic_prefix = (current_BWP->cyclicprefix==NULL) ? 0 : *current_BWP->cyclicprefix;
|
||||||
|
|
||||||
NR_PUCCH_Config_t *pucch_Config = current_BWP->pucch_Config;
|
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");
|
LOG_D(NR_MAC,"pucch_acknak: Filling dedicated configuration for PUCCH\n");
|
||||||
|
|
||||||
AssertFatal(pucch_Config->resourceSetToAddModList!=NULL,
|
AssertFatal(pucch_Config->resourceSetToAddModList!=NULL,
|
||||||
@@ -1166,6 +1166,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
|
|||||||
break;
|
break;
|
||||||
case NR_PUCCH_Resource__format_PR_format2 :
|
case NR_PUCCH_Resource__format_PR_format2 :
|
||||||
pucch_pdu->format_type = 2;
|
pucch_pdu->format_type = 2;
|
||||||
|
pucch_pdu->sr_flag = O_sr;
|
||||||
pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols;
|
pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols;
|
||||||
pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex;
|
pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex;
|
||||||
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
|
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
|
||||||
@@ -2209,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
|
// main function to configure parameters of current BWP
|
||||||
void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
||||||
NR_ServingCellConfigCommon_t *scc,
|
NR_ServingCellConfigCommon_t *scc,
|
||||||
@@ -2375,7 +2390,6 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
|||||||
else
|
else
|
||||||
UL_BWP->pucch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup;
|
UL_BWP->pucch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup;
|
||||||
|
|
||||||
|
|
||||||
if(UE) {
|
if(UE) {
|
||||||
// setting PDCCH related structures for sched_ctrl
|
// setting PDCCH related structures for sched_ctrl
|
||||||
sched_ctrl->search_space = get_searchspace(scc,
|
sched_ctrl->search_space = get_searchspace(scc,
|
||||||
@@ -2410,6 +2424,8 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
|||||||
if (UL_BWP->csi_MeasConfig)
|
if (UL_BWP->csi_MeasConfig)
|
||||||
compute_csi_bitlen (UL_BWP->csi_MeasConfig, UE->csi_report_template);
|
compute_csi_bitlen (UL_BWP->csi_MeasConfig, UE->csi_report_template);
|
||||||
|
|
||||||
|
set_max_fb_time(UL_BWP, DL_BWP);
|
||||||
|
set_sched_pucch_list(sched_ctrl, UL_BWP, scc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ra) {
|
if(ra) {
|
||||||
@@ -2456,6 +2472,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
|||||||
NR_RNTI_C,
|
NR_RNTI_C,
|
||||||
target_ss,
|
target_ss,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_srs_stats(NR_UE_info_t *UE) {
|
void reset_srs_stats(NR_UE_info_t *UE) {
|
||||||
@@ -2553,6 +2570,31 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf
|
|||||||
return (UE);
|
return (UE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl,
|
||||||
|
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 = calloc(list_size, sizeof(*sched_ctrl->sched_pucch));
|
||||||
|
sched_ctrl->sched_pucch_size = list_size;
|
||||||
|
}
|
||||||
|
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; i<list_size; i++){
|
||||||
|
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_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,
|
void create_dl_harq_list(NR_UE_sched_ctrl_t *sched_ctrl,
|
||||||
const NR_PDSCH_ServingCellConfig_t *pdsch) {
|
const NR_PDSCH_ServingCellConfig_t *pdsch) {
|
||||||
const int nrofHARQ = pdsch && pdsch->nrofHARQ_ProcessesForPDSCH ?
|
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,
|
void get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config,
|
||||||
nr_dci_format_t dci_format,
|
nr_dci_format_t dci_format,
|
||||||
int *max_fb_time,
|
|
||||||
uint8_t *pdsch_to_harq_feedback) {
|
uint8_t *pdsch_to_harq_feedback) {
|
||||||
|
|
||||||
if (dci_format == NR_DL_DCI_FORMAT_1_0) {
|
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;
|
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 {
|
else {
|
||||||
AssertFatal(pucch_Config!=NULL,"pucch_Config shouldn't be null here\n");
|
AssertFatal(pucch_Config!=NULL,"pucch_Config shouldn't be null here\n");
|
||||||
if(pucch_Config->dl_DataToUL_ACK != NULL) {
|
if(pucch_Config->dl_DataToUL_ACK != NULL) {
|
||||||
for (int i=0; i<8; i++) {
|
for (int i=0; i<8; i++) {
|
||||||
pdsch_to_harq_feedback[i] = *pucch_Config->dl_DataToUL_ACK->list.array[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
|
else
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac,
|
|||||||
const NR_sched_pucch_t *pucch,
|
const NR_sched_pucch_t *pucch,
|
||||||
NR_UE_info_t* UE)
|
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)
|
if (future_ul_tti_req->SFN != pucch->frame || future_ul_tti_req->Slot != pucch->ul_slot)
|
||||||
LOG_W(MAC,
|
LOG_W(MAC,
|
||||||
"Current %d.%d : future UL_tti_req's frame.slot %4d.%2d does not match PUCCH %4d.%2d\n",
|
"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,
|
future_ul_tti_req->Slot,
|
||||||
pucch->frame,
|
pucch->frame,
|
||||||
pucch->ul_slot);
|
pucch->ul_slot);
|
||||||
|
|
||||||
// n_pdus is number of pdus, so, in the array, it is the index of the next free element
|
// 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) ) {
|
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",
|
LOG_E(NR_MAC,"future_ul_tti_req->n_pdus %d is full, slot: %d, sr flag %d dropping request\n",
|
||||||
@@ -69,7 +70,7 @@ static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac,
|
|||||||
|
|
||||||
LOG_D(NR_MAC,
|
LOG_D(NR_MAC,
|
||||||
"%s %4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, DAI %d, CSI %d on res %d\n",
|
"%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,
|
frame,
|
||||||
slot,
|
slot,
|
||||||
pucch->frame,
|
pucch->frame,
|
||||||
@@ -130,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,
|
void nr_schedule_pucch(gNB_MAC_INST *nrmac,
|
||||||
frame_t frameP,
|
frame_t frameP,
|
||||||
sub_frame_t slotP)
|
sub_frame_t slotP)
|
||||||
@@ -139,23 +154,25 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac,
|
|||||||
|
|
||||||
UE_iterator(nrmac->UE_info.list, UE) {
|
UE_iterator(nrmac->UE_info.list, UE) {
|
||||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||||
const int n = sizeof(sched_ctrl->sched_pucch) / sizeof(*sched_ctrl->sched_pucch);
|
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
|
||||||
for (int i = 0; i < n; i++) {
|
const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs];
|
||||||
NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[i];
|
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[0].ServingCellConfigCommon;
|
||||||
const uint16_t O_ack = curr_pucch->dai_c;
|
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||||
const uint16_t O_csi = curr_pucch->csi_bits;
|
AssertFatal(tdd || nrmac->common_channels[0].frame_type == FDD, "Dynamic TDD not handled yet\n");
|
||||||
const uint8_t O_sr = curr_pucch->sr_flag;
|
const int pucch_index = get_pucch_index(slotP, n_slots_frame, tdd, sched_ctrl->sched_pucch_size);
|
||||||
if (O_ack + O_csi + O_sr == 0
|
NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index];
|
||||||
|| frameP != curr_pucch->frame
|
if (!curr_pucch->active)
|
||||||
|| slotP != curr_pucch->ul_slot)
|
continue;
|
||||||
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));
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,14 +203,16 @@ void nr_csi_meas_reporting(int Mod_idP,
|
|||||||
if(pucchcsires->uplinkBandwidthPartId != ul_bwp->bwp_id)
|
if(pucchcsires->uplinkBandwidthPartId != ul_bwp->bwp_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// we schedule CSI reporting max_fb_time slots in advance
|
||||||
int period, offset;
|
int period, offset;
|
||||||
csi_period_offset(csirep, NULL, &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
|
// 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 ((sched_frame*n_slots_frame + sched_slot - offset)%period != 0)
|
||||||
if (frame % (period / n_slots_frame) != offset / n_slots_frame)
|
|
||||||
continue;
|
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 NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
|
||||||
const int n = pucchresset->resourceList.list.count;
|
const int n = pucchresset->resourceList.list.count;
|
||||||
@@ -204,19 +223,18 @@ void nr_csi_meas_reporting(int Mod_idP,
|
|||||||
AssertFatal(res_index < n,
|
AssertFatal(res_index < n,
|
||||||
"CSI pucch resource %ld not found among PUCCH resources\n", pucchcsires->pucch_Resource);
|
"CSI pucch resource %ld not found among PUCCH resources\n", pucchcsires->pucch_Resource);
|
||||||
|
|
||||||
// find free PUCCH that is in order with possibly existing PUCCH
|
const NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels[0].ServingCellConfigCommon;
|
||||||
// schedulings (other CSI, SR)
|
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||||
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[1];
|
AssertFatal(tdd || RC.nrmac[Mod_idP]->common_channels[0].frame_type == FDD, "Dynamic TDD not handled yet\n");
|
||||||
AssertFatal(curr_pucch->csi_bits == 0
|
const int pucch_index = get_pucch_index(sched_slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size);
|
||||||
&& !curr_pucch->sr_flag
|
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index];
|
||||||
&& curr_pucch->dai_c == 0,
|
AssertFatal(curr_pucch->active == false, "CSI structure is scheduled in advance. It should be free!\n");
|
||||||
"PUCCH not free at index 1 for UE %04x\n",
|
|
||||||
UE->rnti);
|
|
||||||
curr_pucch->r_pucch = -1;
|
curr_pucch->r_pucch = -1;
|
||||||
curr_pucch->frame = frame;
|
curr_pucch->frame = sched_frame;
|
||||||
curr_pucch->ul_slot = sched_slot;
|
curr_pucch->ul_slot = sched_slot;
|
||||||
curr_pucch->resource_indicator = res_index;
|
curr_pucch->resource_indicator = res_index;
|
||||||
curr_pucch->csi_bits += nr_get_csi_bitlen(UE->csi_report_template, csi_report_id);
|
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;
|
int bwp_start = ul_bwp->BWPStart;
|
||||||
|
|
||||||
@@ -235,7 +253,7 @@ void nr_csi_meas_reporting(int Mod_idP,
|
|||||||
len = pucchres->format.choice.format2->nrofPRBs;
|
len = pucchres->format.choice.format2->nrofPRBs;
|
||||||
mask = SL_to_bitmap(pucchres->format.choice.format2->startingSymbolIndex, pucchres->format.choice.format2->nrofSymbols);
|
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;
|
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;
|
break;
|
||||||
case NR_PUCCH_Resource__format_PR_format3:
|
case NR_PUCCH_Resource__format_PR_format3:
|
||||||
len = pucchres->format.choice.format3->nrofPRBs;
|
len = pucchres->format.choice.format3->nrofPRBs;
|
||||||
@@ -252,7 +270,7 @@ void nr_csi_meas_reporting(int Mod_idP,
|
|||||||
// verify resources are free
|
// verify resources are free
|
||||||
for (int i = start; i < start + len; ++i) {
|
for (int i = start; i < start + len; ++i) {
|
||||||
if((vrb_map_UL[i+bwp_start] & mask) != 0) {
|
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));
|
memset(curr_pucch, 0, sizeof(*curr_pucch));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -993,26 +1011,12 @@ 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,
|
void set_pucch_allocation(const NR_PUCCH_Config_t *pucch_Config,
|
||||||
NR_sched_pucch_t *pucch,
|
const NR_ServingCellConfigCommon_t *scc,
|
||||||
uint16_t *vrb_map_UL,
|
const int r_pucch,
|
||||||
const NR_ServingCellConfigCommon_t *scc,
|
const int bwp_size,
|
||||||
NR_PUCCH_Config_t *pucch_Config,
|
NR_sched_pucch_t *pucch)
|
||||||
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){
|
if(r_pucch<0){
|
||||||
const NR_PUCCH_Resource_t *resource = pucch_Config->resourceToAddModList->list.array[0];
|
const NR_PUCCH_Resource_t *resource = pucch_Config->resourceToAddModList->list.array[0];
|
||||||
DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
|
DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
|
||||||
@@ -1031,6 +1035,14 @@ bool test_acknack_vrb_occupation(NR_UE_sched_ctrl_t *sched_ctrl,
|
|||||||
&pucch->nr_of_symb,
|
&pucch->nr_of_symb,
|
||||||
&pucch->start_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
|
// verifying occupation of PRBs for ACK/NACK on dedicated pucch
|
||||||
for (int l=0; l<pucch->nr_of_symb; l++) {
|
for (int l=0; l<pucch->nr_of_symb; l++) {
|
||||||
@@ -1048,263 +1060,10 @@ bool test_acknack_vrb_occupation(NR_UE_sched_ctrl_t *sched_ctrl,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this function returns an index to NR_sched_pucch structure
|
void set_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch,
|
||||||
// currently this structure contains PUCCH0 at index 0 and PUCCH2 at index 1
|
uint16_t *vrb_map_UL,
|
||||||
// if the function returns -1 it was not possible to schedule acknack
|
const int bwp_start)
|
||||||
// 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) {
|
|
||||||
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 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");
|
|
||||||
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]
|
|
||||||
* * 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;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (ind_found!=-1)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 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 (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,"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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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; l<pucch->nr_of_symb; l++) {
|
for (int l=0; l<pucch->nr_of_symb; l++) {
|
||||||
uint16_t symb = SL_to_bitmap(pucch->start_symb+l, 1);
|
uint16_t symb = SL_to_bitmap(pucch->start_symb+l, 1);
|
||||||
int prb;
|
int prb;
|
||||||
@@ -1314,7 +1073,115 @@ int nr_acknack_scheduling(int mod_id,
|
|||||||
prb = pucch->prb_start;
|
prb = pucch->prb_start;
|
||||||
vrb_map_UL[bwp_start+prb] |= symb;
|
vrb_map_UL[bwp_start+prb] |= symb;
|
||||||
}
|
}
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
NR_UE_info_t *UE,
|
||||||
|
frame_t frame,
|
||||||
|
sub_frame_t slot,
|
||||||
|
int r_pucch,
|
||||||
|
int is_common)
|
||||||
|
{
|
||||||
|
|
||||||
|
const int CC_id = 0;
|
||||||
|
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 || 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;
|
||||||
|
|
||||||
|
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||||
|
NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config;
|
||||||
|
|
||||||
|
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)
|
||||||
|
dci_format = UE->current_DL_BWP.dci_format;
|
||||||
|
|
||||||
|
uint8_t pdsch_to_harq_feedback[8];
|
||||||
|
get_pdsch_to_harq_feedback(pucch_Config, dci_format, pdsch_to_harq_feedback);
|
||||||
|
|
||||||
|
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)) & 1023;
|
||||||
|
// 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 &&
|
||||||
|
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->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)
|
||||||
|
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,pucch_index,f,curr_pucch->dai_c,curr_pucch->csi_bits);
|
||||||
|
return pucch_index; // index of current PUCCH structure
|
||||||
|
}
|
||||||
|
else if (curr_pucch->active) {
|
||||||
|
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
|
||||||
|
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,
|
||||||
|
bwp_start,
|
||||||
|
bwp_size);
|
||||||
|
if(!ret) {
|
||||||
|
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
|
||||||
|
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;
|
||||||
|
|
||||||
|
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,pucch_index,f,curr_pucch->dai_c);
|
||||||
|
|
||||||
|
// blocking resources for current PUCCH in VRB map
|
||||||
|
set_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start);
|
||||||
|
|
||||||
|
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);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1322,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))
|
if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slot / 64], slot))
|
||||||
return;
|
return;
|
||||||
|
const int CC_id = 0;
|
||||||
UE_iterator(nrmac->UE_info.list, UE) {
|
UE_iterator(nrmac->UE_info.list, UE) {
|
||||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||||
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
|
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
|
||||||
@@ -1340,104 +1207,60 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot)
|
|||||||
|
|
||||||
int SR_period; int SR_offset;
|
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
|
// convert to int to avoid underflow of uint
|
||||||
int sfn_sf = SFN * n_slots_frame + slot;
|
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);
|
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)
|
if ((sfn_sf - SR_offset) % SR_period != 0)
|
||||||
continue;
|
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;
|
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
|
NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0]; // set with formats 0,1
|
||||||
int n_list = pucchresset->resourceList.list.count;
|
int n_list = pucchresset->resourceList.list.count;
|
||||||
for (int i=0; i<n_list; i++) {
|
for (int i=0; i<n_list; i++) {
|
||||||
if (*pucchresset->resourceList.list.array[i] == *PucchResourceId )
|
if (*pucchresset->resourceList.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
|
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
|
||||||
* with the resource_indicator, it means we already allocated that PUCCH
|
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||||
* resource for AckNack (e.g., the UE has been scheduled often), and we
|
AssertFatal(tdd || nrmac->common_channels[CC_id].frame_type == FDD, "Dynamic TDD not handled yet\n");
|
||||||
* just need to add the SR_flag. Otherwise, just allocate in the internal
|
const int pucch_index = get_pucch_index(slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size);
|
||||||
* PUCCH resource, and nr_schedule_pucch() will handle the rest */
|
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index];
|
||||||
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;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nfapi_allocated) // break scheduling resource loop, continue next UE
|
if (curr_pucch->active &&
|
||||||
break;
|
curr_pucch->frame == SFN &&
|
||||||
|
curr_pucch->ul_slot == slot &&
|
||||||
/* we did not find it: check if current PUCCH is for the current slot, in
|
curr_pucch->resource_indicator == idx)
|
||||||
* 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);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
curr_pucch->sr_flag = true;
|
curr_pucch->sr_flag = true;
|
||||||
} else {
|
else if (curr_pucch->active) {
|
||||||
NR_sched_pucch_t sched_sr = {
|
AssertFatal(1==0, "This shouldn't happen! curr_pucch frame.slot %d.%d not matching with SR function frame.slot %d.%d\n",
|
||||||
.frame = SFN,
|
curr_pucch->frame, curr_pucch->ul_slot, SFN, slot);
|
||||||
.ul_slot = slot,
|
continue;
|
||||||
.sr_flag = true,
|
}
|
||||||
.resource_indicator = found,
|
else {
|
||||||
.r_pucch = -1
|
uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[slot * MAX_BWP_SIZE];
|
||||||
};
|
const int bwp_start = ul_bwp->BWPStart;
|
||||||
nr_fill_nfapi_pucch(nrmac, SFN, slot, &sched_sr, UE);
|
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,
|
||||||
|
bwp_start,
|
||||||
|
bwp_size);
|
||||||
|
if (!ret) {
|
||||||
|
LOG_E(NR_MAC,"Cannot schedule SR. PRBs not available\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
set_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ void nr_csi_meas_reporting(int Mod_idP,
|
|||||||
frame_t frameP,
|
frame_t frameP,
|
||||||
sub_frame_t slotP);
|
sub_frame_t slotP);
|
||||||
|
|
||||||
int nr_acknack_scheduling(int Mod_idP,
|
int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||||
NR_UE_info_t *UE,
|
NR_UE_info_t *UE,
|
||||||
frame_t frameP,
|
frame_t frameP,
|
||||||
sub_frame_t slotP,
|
sub_frame_t slotP,
|
||||||
@@ -218,7 +218,6 @@ int nr_acknack_scheduling(int Mod_idP,
|
|||||||
|
|
||||||
void get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config,
|
void get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config,
|
||||||
nr_dci_format_t dci_format,
|
nr_dci_format_t dci_format,
|
||||||
int *max_fb_time,
|
|
||||||
uint8_t *pdsch_to_harq_feedback);
|
uint8_t *pdsch_to_harq_feedback);
|
||||||
|
|
||||||
void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu,
|
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);
|
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,
|
||||||
|
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_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);
|
const int get_ul_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot);
|
||||||
|
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ typedef struct NR_UE_UL_BWP {
|
|||||||
uint8_t transform_precoding;
|
uint8_t transform_precoding;
|
||||||
uint8_t mcs_table;
|
uint8_t mcs_table;
|
||||||
nr_dci_format_t dci_format;
|
nr_dci_format_t dci_format;
|
||||||
|
int max_fb_time;
|
||||||
} NR_UE_UL_BWP_t;
|
} NR_UE_UL_BWP_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -354,6 +355,7 @@ typedef struct UE_info {
|
|||||||
} NR_UE_mac_ce_ctrl_t;
|
} NR_UE_mac_ce_ctrl_t;
|
||||||
|
|
||||||
typedef struct NR_sched_pucch {
|
typedef struct NR_sched_pucch {
|
||||||
|
bool active;
|
||||||
int frame;
|
int frame;
|
||||||
int ul_slot;
|
int ul_slot;
|
||||||
bool sr_flag;
|
bool sr_flag;
|
||||||
@@ -560,9 +562,12 @@ typedef struct {
|
|||||||
/// corresponding to the sched_pusch/sched_pdsch structures below
|
/// corresponding to the sched_pusch/sched_pdsch structures below
|
||||||
int cce_index;
|
int cce_index;
|
||||||
uint8_t aggregation_level;
|
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
|
||||||
NR_sched_pucch_t sched_pucch[2];
|
/// 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;
|
||||||
|
|
||||||
/// Sched PUSCH: scheduling decisions, copied into HARQ and cleared every TTI
|
/// Sched PUSCH: scheduling decisions, copied into HARQ and cleared every TTI
|
||||||
NR_sched_pusch_t sched_pusch;
|
NR_sched_pusch_t sched_pusch;
|
||||||
|
|||||||
Reference in New Issue
Block a user