reworking gNB PUCCH scheduling

This commit is contained in:
francescomani
2022-10-07 15:26:30 +02:00
parent 84611333c8
commit 86cf5e704d
5 changed files with 231 additions and 365 deletions
+4 -6
View File
@@ -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,10 +236,9 @@ 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); nr_sr_reporting(RC.nrmac[module_idP], frame, slot, module_idP);
// This schedule SR after PUCCH for multiplexing nr_schedule_pucch(RC.nrmac[module_idP], frame, slot);
nr_sr_reporting(RC.nrmac[module_idP], frame, slot);
stop_meas(&RC.nrmac[module_idP]->eNB_scheduler); stop_meas(&RC.nrmac[module_idP]->eNB_scheduler);
@@ -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,
@@ -2375,6 +2375,17 @@ 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;
UL_BWP->max_fb_time = 0;
if(DL_BWP->dci_format != NR_DL_DCI_FORMAT_1_0 &&
UL_BWP->pucch_Config) {
for (int i=0; i<UL_BWP->pucch_Config->dl_DataToUL_ACK->list.count; i++) {
if(*UL_BWP->pucch_Config->dl_DataToUL_ACK->list.array[i] > UL_BWP->max_fb_time)
UL_BWP->max_fb_time = *UL_BWP->pucch_Config->dl_DataToUL_ACK->list.array[i];
}
}
else
UL_BWP->max_fb_time = 8; // default value
if(UE) { if(UE) {
// setting PDCCH related structures for sched_ctrl // setting PDCCH related structures for sched_ctrl
@@ -2410,6 +2421,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_sched_pucch_list(sched_ctrl, UL_BWP, scc);
} }
if(ra) { if(ra) {
@@ -2456,6 +2469,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 +2567,34 @@ 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,
NR_UE_UL_BWP_t *ul_bwp,
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;
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 = malloc(list_size * sizeof(*sched_ctrl->sched_pucch));
sched_ctrl->sched_pucch_size = list_size;
for(int i=0; i<list_size; i++) {
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[i];
memset(curr_pucch, 0, sizeof(*curr_pucch));
}
}
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
+173 -348
View File
@@ -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",
@@ -139,22 +140,19 @@ 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); for (int i = 0; i < sched_ctrl->sched_pucch_size; i++) {
for (int i = 0; i < n; i++) {
NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[i]; NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[i];
const uint16_t O_ack = curr_pucch->dai_c; const uint16_t O_ack = curr_pucch->dai_c;
const uint16_t O_csi = curr_pucch->csi_bits; const uint16_t O_csi = curr_pucch->csi_bits;
const uint8_t O_sr = curr_pucch->sr_flag; const uint8_t O_sr = curr_pucch->sr_flag;
if (O_ack + O_csi + O_sr == 0 if (curr_pucch->active == true &&
|| frameP != curr_pucch->frame frameP == curr_pucch->frame &&
|| slotP != curr_pucch->ul_slot) slotP == curr_pucch->ul_slot) {
continue; 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);
if (O_csi > 0) nr_fill_nfapi_pucch(nrmac, frameP, slotP, curr_pucch, UE);
LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %04x in %4d.%2d O_ack %d, O_sr %d, O_csi %d\n", memset(curr_pucch, 0, sizeof(*curr_pucch));
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 +184,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;
@@ -206,17 +206,21 @@ void nr_csi_meas_reporting(int Mod_idP,
// find free PUCCH that is in order with possibly existing PUCCH // find free PUCCH that is in order with possibly existing PUCCH
// schedulings (other CSI, SR) // schedulings (other CSI, SR)
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[1]; NR_sched_pucch_t *curr_pucch = NULL;
AssertFatal(curr_pucch->csi_bits == 0 for (int i=0; i<sched_ctrl->sched_pucch_size; i++) {
&& !curr_pucch->sr_flag curr_pucch = &sched_ctrl->sched_pucch[i];
&& curr_pucch->dai_c == 0, if (!curr_pucch->active)
"PUCCH not free at index 1 for UE %04x\n", break; // found an available pucch structure
}
AssertFatal(curr_pucch,
"PUCCH structure not found for UE %04x\n",
UE->rnti); 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 +239,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 +256,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 +997,17 @@ 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, bool test_pucch0_vrb_occupation(NR_UE_sched_ctrl_t *sched_ctrl,
NR_sched_pucch_t *pucch, NR_sched_pucch_t *pucch,
uint16_t *vrb_map_UL, uint16_t *vrb_map_UL,
const NR_ServingCellConfigCommon_t *scc, const NR_ServingCellConfigCommon_t *scc,
NR_PUCCH_Config_t *pucch_Config, NR_PUCCH_Config_t *pucch_Config,
int r_pucch, int r_pucch,
int bwp_start, int bwp_start,
int bwp_size) { int bwp_size) {
// We assume initial cyclic shift is always 0 so different pucch resources can't overlap // 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);
@@ -1049,15 +1044,15 @@ bool test_acknack_vrb_occupation(NR_UE_sched_ctrl_t *sched_ctrl,
} }
// this function returns an index to NR_sched_pucch structure // 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 // 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 nr_acknack_scheduling(int mod_id,
NR_UE_info_t *UE, NR_UE_info_t *UE,
frame_t frame, frame_t frame,
sub_frame_t slot, sub_frame_t slot,
int r_pucch, int r_pucch,
int is_common) { int is_common)
{
const int CC_id = 0; const int CC_id = 0;
const int minfbtime = RC.nrmac[mod_id]->minRXTXTIMEpdsch; const int minfbtime = RC.nrmac[mod_id]->minRXTXTIMEpdsch;
const NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels[CC_id].ServingCellConfigCommon; const NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels[CC_id].ServingCellConfigCommon;
@@ -1066,10 +1061,8 @@ int nr_acknack_scheduling(int mod_id,
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; 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"); 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 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; const int first_ul_slot_period = tdd ? tdd->nrofDownlinkSlots : 0;
/* for the moment, we consider: /* for the moment, we consider:
* * only pucch_sched[0] holds HARQ (and SR) * * only pucch_sched[0] holds HARQ (and SR)
* * we do not multiplex with CSI, which is always in pucch_sched[2] * * we do not multiplex with CSI, which is always in pucch_sched[2]
@@ -1082,247 +1075,110 @@ int nr_acknack_scheduling(int mod_id,
int bwp_start = ul_bwp->BWPStart; int bwp_start = ul_bwp->BWPStart;
int bwp_size = ul_bwp->BWPSize; 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; nr_dci_format_t dci_format = NR_DL_DCI_FORMAT_1_0;
if(is_common == 0) if(is_common == 0)
dci_format = UE->current_DL_BWP.dci_format; dci_format = UE->current_DL_BWP.dci_format;
uint8_t pdsch_to_harq_feedback[8]; uint8_t pdsch_to_harq_feedback[8];
int max_fb_time = 0; get_pdsch_to_harq_feedback(pucch_Config, dci_format, pdsch_to_harq_feedback);
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); for (int f=0; f<8; f++) {
/* there is a HARQ. Check whether we can use it for this ACKNACK */ // can't schedule ACKNACK before minimum feedback time
if (pucch->dai_c > 0) { if(pdsch_to_harq_feedback[f] < minfbtime)
/* this UE already has a PUCCH occasion */ continue;
// Find the right timing_indicator value. const int pucch_slot = (slot + pdsch_to_harq_feedback[f]) % n_slots_frame;
int i = 0; // check if the slot is UL
while (i < 8) { if(pucch_slot%nr_slots_period < first_ul_slot_period)
int diff = pucch->ul_slot - slot; continue;
if (diff<0) const int pucch_frame = frame + ((slot + pdsch_to_harq_feedback[f]) / n_slots_frame);
diff += n_slots_frame; int inactive_pucch = -1;
if (pdsch_to_harq_feedback[i] == diff && NR_sched_pucch_t *curr_pucch = NULL;
pdsch_to_harq_feedback[i] >= minfbtime) for (int i=0; i<sched_ctrl->sched_pucch_size; i++) {
break; curr_pucch = &sched_ctrl->sched_pucch[i];
++i; // if there is already an active pucch for this frame and slot
} if (curr_pucch->active &&
if (i >= 8) { curr_pucch->frame == pucch_frame &&
// we cannot reach this timing anymore, allocate and try again curr_pucch->ul_slot == pucch_slot) {
const int f = pucch->frame; LOG_D(NR_MAC, "In %s: pucch_acknak DL %4d.%2d, UL_ACK %4d.%2d Bits already in current PUCCH: DAI_C %d CSI %d\n",
const int s = pucch->ul_slot; __FUNCTION__, frame, slot, pucch_frame, pucch_slot, curr_pucch->dai_c, curr_pucch->csi_bits);
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); // we can't schedule if short pucch is already full
if (!(csi_pucch && if (curr_pucch->csi_bits == 0 &&
csi_pucch->csi_bits > 0 && curr_pucch->dai_c == 2)
csi_pucch->frame == f && continue;
csi_pucch->ul_slot == s)) // if there is CSI but simultaneous HARQ+CSI is disable we can't schedule
nr_fill_nfapi_pucch(RC.nrmac[mod_id], frame, slot, pucch, UE); if(!curr_pucch->simultaneous_harqcsi &&
memset(pucch, 0, sizeof(*pucch)); curr_pucch->csi_bits>0)
pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; continue;
if(((s + 1)%nr_slots_period) == 0) // TODO we can't schedule more than 11 bits in PUCCH2 for now
pucch->ul_slot = (s + 1 + first_ul_slot_period) % n_slots_frame; if (curr_pucch->csi_bits + curr_pucch->dai_c >= 10)
else continue;
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; // otherwise we can schedule in this active PUCCH
pucch->dai_c++; // no need to check VRB occupation because already done when PUCCH has been activated
// if there is CSI in this slot update the HARQ information for that one too curr_pucch->timing_indicator = f;
if (csi_pucch && curr_pucch->dai_c++;
csi_pucch->csi_bits > 0 && LOG_D(NR_MAC, "In %s: DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d CSI %d\n",
csi_pucch->frame == pucch->frame && __FUNCTION__,frame,slot,curr_pucch->frame,curr_pucch->ul_slot,i,f,curr_pucch->dai_c,curr_pucch->csi_bits);
csi_pucch->ul_slot == pucch->ul_slot) { return i; // index of current PUCCH structure
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) else if (!curr_pucch->active)
break; inactive_pucch = i;
} }
// advance to the next ul slot if (inactive_pucch>0) {
const int f = pucch->frame; curr_pucch = &sched_ctrl->sched_pucch[inactive_pucch];
const int s = pucch->ul_slot; // checking if in ul_slot the resources potentially to be assigned to this PUCCH are available
pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch_slot * MAX_BWP_SIZE];
if(((s + 1)%nr_slots_period) == 0) bool ret = test_pucch0_vrb_occupation(sched_ctrl,
pucch->ul_slot = (s + 1 + first_ul_slot_period) % n_slots_frame; curr_pucch,
else vrb_map_UL,
pucch->ul_slot = (s + 1) % n_slots_frame; scc,
} pucch_Config,
if (ind_found==-1) { r_pucch,
LOG_D(NR_MAC, bwp_start,
"%4d.%2d could not find pdsch_to_harq_feedback for UE %04x: earliest " bwp_size);
"ack slot %d\n", if(!ret) {
frame, LOG_D(NR_MAC, "In %s: DL %4d.%2d, UL_ACK %4d.%2d PRB resources for this occasion are already occupied, move to the following occasion\n",
slot, __FUNCTION__,frame,slot,curr_pucch->frame,curr_pucch->ul_slot);
UE->rnti, continue;
pucch->ul_slot); }
return -1; // 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;
if (csi_pucch && LOG_D(NR_MAC, "In %s: DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d\n",
csi_pucch->csi_bits > 0 && __FUNCTION__,frame,slot,curr_pucch->frame,curr_pucch->ul_slot,inactive_pucch,f,curr_pucch->dai_c);
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); // blocking resources for current PUCCH in VRB map
return 1; for (int l=0; l<curr_pucch->nr_of_symb; l++) {
uint16_t symb = SL_to_bitmap(curr_pucch->start_symb+l, 1);
int prb;
if (l==1 && curr_pucch->second_hop_prb != 0)
prb = curr_pucch->second_hop_prb;
else
prb = curr_pucch->prb_start;
vrb_map_UL[bwp_start+prb] |= symb;
}
return inactive_pucch; // index of current PUCCH structure
} }
} }
LOG_D(NR_MAC, "In %s: DL %4d.%2d, Couldn't find scheduling occasion for this HARQ process\n",
pucch->timing_indicator = ind_found; // index in the list of timing indicators __FUNCTION__, frame, slot);
return -1;
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++) {
uint16_t symb = SL_to_bitmap(pucch->start_symb+l, 1);
int prb;
if (l==1 && pucch->second_hop_prb != 0)
prb = pucch->second_hop_prb;
else
prb = pucch->prb_start;
vrb_map_UL[bwp_start+prb] |= symb;
}
return 0;
} }
void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot, int mod_id)
{ {
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;
int CC_id = 0;
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
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;
@@ -1349,95 +1205,64 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot)
LOG_D(NR_MAC, "%4d.%2d Scheduling Request identified\n", SFN, slot); LOG_D(NR_MAC, "%4d.%2d Scheduling Request identified\n", SFN, slot);
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 NR_sched_pucch_t *curr_pucch = NULL;
* with the resource_indicator, it means we already allocated that PUCCH bool found = false;
* resource for AckNack (e.g., the UE has been scheduled often), and we int free_pucch = -1;
* just need to add the SR_flag. Otherwise, just allocate in the internal for (int i=0; i<sched_ctrl->sched_pucch_size; i++) {
* PUCCH resource, and nr_schedule_pucch() will handle the rest */ curr_pucch = &sched_ctrl->sched_pucch[i];
NR_PUCCH_Resource_t *pucch_res = pucch_Config->resourceToAddModList->list.array[found]; if (curr_pucch->active &&
/* for the moment, can only handle SR on PUCCH Format 0 */ curr_pucch->frame == SFN &&
DevAssert(pucch_res->format.present == NR_PUCCH_Resource__format_PR_format0); curr_pucch->ul_slot == slot &&
nfapi_nr_ul_tti_request_t *ul_tti_req = &nrmac->UL_tti_req_ahead[0][slot]; curr_pucch->resource_indicator == found) {
bool nfapi_allocated = false; curr_pucch->sr_flag = true;
for (int i = 0; i < ul_tti_req->n_pdus; ++i) { found = true;
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; break;
} }
else if (!curr_pucch->active)
free_pucch = i; // found an available pucch structure
} }
AssertFatal(found || free_pucch>0, "Coulnd't find an available PUCCH resource to schedule SR\n");
if (nfapi_allocated) // break scheduling resource loop, continue next UE if (!found) {
break; uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[slot * MAX_BWP_SIZE];
int bwp_start = ul_bwp->BWPStart;
/* we did not find it: check if current PUCCH is for the current slot, in int bwp_size = ul_bwp->BWPSize;
* which case we add the SR to it; otherwise, allocate SR separately */ NR_sched_pucch_t *sched_sr = &sched_ctrl->sched_pucch[free_pucch];
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[0]; bool ret = test_pucch0_vrb_occupation(sched_ctrl,
if (curr_pucch->frame == SFN && curr_pucch->ul_slot == slot) { sched_sr,
if (curr_pucch->resource_indicator != found) { vrb_map_UL,
LOG_W(NR_MAC, "%4d.%2d expected PUCCH in this slot to have resource indicator of SR (%d), skipping SR\n", SFN, slot, found); scc,
pucch_Config,
-1,
bwp_start,
bwp_size);
if (!ret) {
LOG_E(NR_MAC,"Cannot schedule SR. PRBs not available\n");
continue; continue;
} }
curr_pucch->sr_flag = true; sched_sr->frame = SFN;
} else { sched_sr->ul_slot = slot;
NR_sched_pucch_t sched_sr = { sched_sr->sr_flag = true;
.frame = SFN, sched_sr->resource_indicator = idx;
.ul_slot = slot, sched_sr->r_pucch = -1;
.sr_flag = true, sched_sr->active = true;
.resource_indicator = found, for (int l=0; l<sched_sr->nr_of_symb; l++) {
.r_pucch = -1 uint16_t symb = SL_to_bitmap(sched_sr->start_symb+l, 1);
}; int prb;
nr_fill_nfapi_pucch(nrmac, SFN, slot, &sched_sr, UE); if (l==1 && sched_sr->second_hop_prb != 0)
prb = sched_sr->second_hop_prb;
else
prb = sched_sr->prb_start;
vrb_map_UL[bwp_start+prb] |= symb;
}
} }
} }
} }
+5 -2
View File
@@ -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,
NR_UE_UL_BWP_t *ul_bwp,
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);
@@ -490,7 +493,7 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
void UL_tti_req_ahead_initialization(gNB_MAC_INST * gNB, NR_ServingCellConfigCommon_t *scc, int n, int CCid); void UL_tti_req_ahead_initialization(gNB_MAC_INST * gNB, NR_ServingCellConfigCommon_t *scc, int n, int CCid);
void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP); void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP, int mod_id);
size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp); size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp);
+5 -1
View File
@@ -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,11 @@ 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, /// PUCCH scheduling information. Array of two: HARQ+SR in the first field,
/// CSI in second. This order is important for nr_acknack_scheduling()! /// CSI in second. This order is important for nr_acknack_scheduling()!
NR_sched_pucch_t sched_pucch[2]; 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;