Simplify preprocessor, retain functionality
* Simplify store_dlsch_buffer() * Simplify assign_rbs_required() * Simplify dlsch_scheduler_pre_processor_partitioning() * Simplify dlsch_scheduler_pre_processor_accounting() and dlsch_scheduler_pre_processor_accounting_allocate() * Simplify allocation printing The original functions used in the fairRR scheduler have been moved to eNB_scheduler_fairRR
This commit is contained in:
@@ -726,7 +726,163 @@ void dlsch_scheduler_pre_processor_reset_fairRR(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function returns the estimated number of RBs required by each UE for downlink scheduling
|
||||||
|
void assign_rbs_required_fairRR(
|
||||||
|
module_id_t Mod_id,
|
||||||
|
frame_t frameP,
|
||||||
|
sub_frame_t subframe,
|
||||||
|
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]) {
|
||||||
|
uint16_t TBS = 0;
|
||||||
|
int UE_id, n, i, j, CC_id, pCCid, tmp;
|
||||||
|
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
||||||
|
eNB_UE_STATS *eNB_UE_stats, *eNB_UE_stats_i, *eNB_UE_stats_j;
|
||||||
|
int N_RB_DL;
|
||||||
|
|
||||||
|
// clear rb allocations across all CC_id
|
||||||
|
for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
|
||||||
|
if (UE_list->active[UE_id] != TRUE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pCCid = UE_PCCID(Mod_id, UE_id);
|
||||||
|
|
||||||
|
// update CQI information across component carriers
|
||||||
|
for (n = 0; n < UE_list->numactiveCCs[UE_id]; n++) {
|
||||||
|
CC_id = UE_list->ordered_CCids[n][UE_id];
|
||||||
|
eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
|
||||||
|
eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// provide the list of CCs sorted according to MCS
|
||||||
|
for (i = 0; i < UE_list->numactiveCCs[UE_id]; ++i) {
|
||||||
|
eNB_UE_stats_i =
|
||||||
|
&UE_list->eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]][UE_id];
|
||||||
|
|
||||||
|
for (j = i + 1; j < UE_list->numactiveCCs[UE_id]; j++) {
|
||||||
|
DevAssert(j < NFAPI_CC_MAX);
|
||||||
|
eNB_UE_stats_j =
|
||||||
|
&UE_list->eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]][UE_id];
|
||||||
|
|
||||||
|
if (eNB_UE_stats_j->dlsch_mcs1 > eNB_UE_stats_i->dlsch_mcs1) {
|
||||||
|
tmp = UE_list->ordered_CCids[i][UE_id];
|
||||||
|
UE_list->ordered_CCids[i][UE_id] = UE_list->ordered_CCids[j][UE_id];
|
||||||
|
UE_list->ordered_CCids[j][UE_id] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total > 0) {
|
||||||
|
LOG_D(MAC, "[preprocessor] assign RB for UE %d\n", UE_id);
|
||||||
|
|
||||||
|
for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) {
|
||||||
|
CC_id = UE_list->ordered_CCids[i][UE_id];
|
||||||
|
eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
|
||||||
|
const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id);
|
||||||
|
|
||||||
|
if (eNB_UE_stats->dlsch_mcs1 == 0) {
|
||||||
|
nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small
|
||||||
|
} else {
|
||||||
|
nb_rbs_required[CC_id][UE_id] = min_rb_unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rbs_required[CC_id][UE_id]);
|
||||||
|
LOG_D(MAC,
|
||||||
|
"[preprocessor] start RB assignement for UE %d CC_id %d dl "
|
||||||
|
"buffer %d (RB unit %d, MCS %d, TBS %d) \n",
|
||||||
|
UE_id,
|
||||||
|
CC_id,
|
||||||
|
UE_list->UE_template[pCCid][UE_id].dl_buffer_total,
|
||||||
|
nb_rbs_required[CC_id][UE_id],
|
||||||
|
eNB_UE_stats->dlsch_mcs1,
|
||||||
|
TBS);
|
||||||
|
N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||||
|
|
||||||
|
/* calculating required number of RBs for each UE */
|
||||||
|
while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total) {
|
||||||
|
nb_rbs_required[CC_id][UE_id] += min_rb_unit;
|
||||||
|
|
||||||
|
if (nb_rbs_required[CC_id][UE_id] > N_RB_DL) {
|
||||||
|
TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, N_RB_DL);
|
||||||
|
nb_rbs_required[CC_id][UE_id] = N_RB_DL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,
|
||||||
|
nb_rbs_required[CC_id][UE_id]);
|
||||||
|
} // end of while
|
||||||
|
|
||||||
|
LOG_D(MAC,
|
||||||
|
"[eNB %d] Frame %d: UE %d on CC %d: RB unit %d, nb_required RB "
|
||||||
|
"%d (TBS %d, mcs %d)\n",
|
||||||
|
Mod_id,
|
||||||
|
frameP,
|
||||||
|
UE_id,
|
||||||
|
CC_id,
|
||||||
|
min_rb_unit,
|
||||||
|
nb_rbs_required[CC_id][UE_id],
|
||||||
|
TBS,
|
||||||
|
eNB_UE_stats->dlsch_mcs1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dlsch_scheduler_pre_processor_allocate_fairRR(
|
||||||
|
module_id_t Mod_id,
|
||||||
|
int UE_id,
|
||||||
|
uint8_t CC_id,
|
||||||
|
int N_RBG,
|
||||||
|
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
||||||
|
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
||||||
|
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) {
|
||||||
|
int i;
|
||||||
|
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
||||||
|
UE_sched_ctrl_t *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
||||||
|
int N_RB_DL =
|
||||||
|
to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||||
|
const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id);
|
||||||
|
|
||||||
|
for (i = 0; i < N_RBG; i++) {
|
||||||
|
if (rballoc_sub[CC_id][i] != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ue_sched_ctl->rballoc_sub_UE[CC_id][i] != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (nb_rbs_remaining[CC_id][UE_id] <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ue_sched_ctl->pre_nb_available_rbs[CC_id]
|
||||||
|
>= nb_rbs_required[CC_id][UE_id])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ue_sched_ctl->dl_pow_off[CC_id] == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((i == N_RBG - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) {
|
||||||
|
// Allocating last, smaller RBG
|
||||||
|
if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit - 1) {
|
||||||
|
rballoc_sub[CC_id][i] = 1;
|
||||||
|
ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
|
||||||
|
|
||||||
|
nb_rbs_remaining[CC_id][UE_id] =
|
||||||
|
nb_rbs_remaining[CC_id][UE_id] - min_rb_unit + 1;
|
||||||
|
ue_sched_ctl->pre_nb_available_rbs[CC_id] =
|
||||||
|
ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Allocating a standard-sized RBG
|
||||||
|
if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit) {
|
||||||
|
rballoc_sub[CC_id][i] = 1;
|
||||||
|
ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
|
||||||
|
|
||||||
|
nb_rbs_remaining[CC_id][UE_id] =
|
||||||
|
nb_rbs_remaining[CC_id][UE_id] - min_rb_unit;
|
||||||
|
ue_sched_ctl->pre_nb_available_rbs[CC_id] =
|
||||||
|
ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done
|
// This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done
|
||||||
void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
|
void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
|
||||||
@@ -792,9 +948,9 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
|
|||||||
|
|
||||||
#if (!defined(PRE_SCD_THREAD))
|
#if (!defined(PRE_SCD_THREAD))
|
||||||
// Store the DLSCH buffer for each logical channel
|
// Store the DLSCH buffer for each logical channel
|
||||||
store_dlsch_buffer(Mod_id,0, frameP, subframeP);
|
store_dlsch_buffer(Mod_id, frameP, subframeP);
|
||||||
// Calculate the number of RBs required by each UE on the basis of logical channel's buffer
|
// Calculate the number of RBs required by each UE on the basis of logical channel's buffer
|
||||||
assign_rbs_required(Mod_id, 0, frameP, subframeP, nb_rbs_required);
|
assign_rbs_required_fairRR(Mod_id, frameP, subframeP, nb_rbs_required);
|
||||||
#else
|
#else
|
||||||
memcpy(nb_rbs_required, pre_nb_rbs_required[dlsch_ue_select_tbl_in_use], sizeof(uint16_t)*MAX_NUM_CCs*MAX_MOBILES_PER_ENB);
|
memcpy(nb_rbs_required, pre_nb_rbs_required[dlsch_ue_select_tbl_in_use], sizeof(uint16_t)*MAX_NUM_CCs*MAX_MOBILES_PER_ENB);
|
||||||
#endif
|
#endif
|
||||||
@@ -855,13 +1011,14 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n ");
|
LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n ");
|
||||||
dlsch_scheduler_pre_processor_allocate (Mod_id,
|
dlsch_scheduler_pre_processor_allocate_fairRR(
|
||||||
UE_id,
|
Mod_id,
|
||||||
CC_id,
|
UE_id,
|
||||||
N_RBG[CC_id],
|
CC_id,
|
||||||
(uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required,
|
N_RBG[CC_id],
|
||||||
(uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required_remaining,
|
(uint16_t(*)[NUMBER_OF_UE_MAX])nb_rbs_required,
|
||||||
rballoc_sub);
|
(uint16_t(*)[NUMBER_OF_UE_MAX])nb_rbs_required_remaining,
|
||||||
|
rballoc_sub);
|
||||||
temp_total_rbs_count -= ue_sched_ctl->pre_nb_available_rbs[CC_id];
|
temp_total_rbs_count -= ue_sched_ctl->pre_nb_available_rbs[CC_id];
|
||||||
temp_total_ue_count--;
|
temp_total_ue_count--;
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,21 @@ void dlsch_scheduler_pre_processor_reset_fairRR(
|
|||||||
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
|
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
|
||||||
uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]);
|
uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]);
|
||||||
|
|
||||||
|
void assign_rbs_required_fairRR(
|
||||||
|
module_id_t Mod_id,
|
||||||
|
frame_t frameP,
|
||||||
|
sub_frame_t subframe,
|
||||||
|
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]);
|
||||||
|
|
||||||
|
void dlsch_scheduler_pre_processor_allocate_fairRR(
|
||||||
|
module_id_t Mod_id,
|
||||||
|
int UE_id,
|
||||||
|
uint8_t CC_id,
|
||||||
|
int N_RBG,
|
||||||
|
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
||||||
|
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
||||||
|
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]);
|
||||||
|
|
||||||
void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
|
void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
|
||||||
frame_t frameP,
|
frame_t frameP,
|
||||||
sub_frame_t subframeP,
|
sub_frame_t subframeP,
|
||||||
|
|||||||
@@ -1184,19 +1184,6 @@ typedef struct {
|
|||||||
int tail_freelist; ///the tail position of the delete list
|
int tail_freelist; ///the tail position of the delete list
|
||||||
} UE_free_list_t;
|
} UE_free_list_t;
|
||||||
|
|
||||||
/// Structure for saving the output of each pre_processor instance
|
|
||||||
typedef struct {
|
|
||||||
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
|
|
||||||
uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
|
|
||||||
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
|
|
||||||
uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX];
|
|
||||||
|
|
||||||
uint32_t bytes_lcid[MAX_MOBILES_PER_ENB][MAX_NUM_LCID];
|
|
||||||
uint32_t wb_pmi[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
|
|
||||||
uint8_t mcs[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
|
|
||||||
|
|
||||||
} pre_processor_results_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* slice specific scheduler for the DL
|
* slice specific scheduler for the DL
|
||||||
*/
|
*/
|
||||||
@@ -1288,8 +1275,6 @@ typedef struct {
|
|||||||
int n_ul;
|
int n_ul;
|
||||||
slice_sched_conf_ul_t ul[MAX_NUM_SLICES];
|
slice_sched_conf_ul_t ul[MAX_NUM_SLICES];
|
||||||
|
|
||||||
pre_processor_results_t pre_processor_results[MAX_NUM_SLICES];
|
|
||||||
|
|
||||||
/// common rb allocation list between slices
|
/// common rb allocation list between slices
|
||||||
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX];
|
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX];
|
||||||
} slice_info_t;
|
} slice_info_t;
|
||||||
|
|||||||
@@ -240,31 +240,25 @@ void dlsch_scheduler_pre_processor_reset(module_id_t module_idP,
|
|||||||
int CC_id,
|
int CC_id,
|
||||||
uint8_t rballoc_sub[N_RBG_MAX]);
|
uint8_t rballoc_sub[N_RBG_MAX]);
|
||||||
|
|
||||||
void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id,
|
|
||||||
int slice_idx,
|
|
||||||
const uint8_t rbs_retx[NFAPI_CC_MAX]);
|
|
||||||
|
|
||||||
void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id,
|
void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id,
|
||||||
int slice_idx,
|
int CC_id,
|
||||||
frame_t frameP,
|
frame_t frameP,
|
||||||
sub_frame_t subframeP,
|
sub_frame_t subframeP,
|
||||||
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB],
|
||||||
uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]);
|
uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB]);
|
||||||
|
|
||||||
void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id,
|
void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id,
|
||||||
int slice_idx,
|
int CC_id,
|
||||||
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB],
|
||||||
uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB],
|
||||||
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
uint8_t rballoc_sub[N_RBG_MAX]);
|
||||||
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]);
|
|
||||||
|
|
||||||
void dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id,
|
void dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id,
|
||||||
int UE_id,
|
int UE_id,
|
||||||
uint8_t CC_id,
|
uint8_t CC_id,
|
||||||
int N_RBG,
|
uint16_t nb_rbs_required,
|
||||||
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
uint16_t *nb_rbs_remaining,
|
||||||
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
uint8_t rballoc_sub[N_RBG_MAX]);
|
||||||
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]);
|
|
||||||
|
|
||||||
/* \brief Function to trigger the eNB scheduling procedure. It is called by PHY at the beginning of each subframe, \f$n$\f
|
/* \brief Function to trigger the eNB scheduling procedure. It is called by PHY at the beginning of each subframe, \f$n$\f
|
||||||
and generates all DLSCH allocations for subframe \f$n\f$ and ULSCH allocations for subframe \f$n+k$\f.
|
and generates all DLSCH allocations for subframe \f$n\f$ and ULSCH allocations for subframe \f$n+k$\f.
|
||||||
@@ -688,8 +682,8 @@ int mac_init(void);
|
|||||||
int add_new_ue(module_id_t Mod_id, int CC_id, rnti_t rnti, int harq_pid, uint8_t rach_resource_type);
|
int add_new_ue(module_id_t Mod_id, int CC_id, rnti_t rnti, int harq_pid, uint8_t rach_resource_type);
|
||||||
int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP);
|
int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP);
|
||||||
|
|
||||||
void store_dlsch_buffer(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframeP);
|
void store_dlsch_buffer(module_id_t Mod_id, frame_t frameP, sub_frame_t subframeP);
|
||||||
void assign_rbs_required(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframe, uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]);
|
void assign_rbs_required(module_id_t Mod_id, int CC_id, uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB]);
|
||||||
|
|
||||||
int prev(UE_list_t *listP, int nodeP, int ul_flag);
|
int prev(UE_list_t *listP, int nodeP, int ul_flag);
|
||||||
void add_ue_list(UE_list_t *listP, int UE_id, int ul_flag);
|
void add_ue_list(UE_list_t *listP, int UE_id, int ul_flag);
|
||||||
|
|||||||
+148
-430
@@ -64,40 +64,34 @@ sort_ue_ul(module_id_t module_idP,
|
|||||||
// This function stores the downlink buffer for all the logical channels
|
// This function stores the downlink buffer for all the logical channels
|
||||||
void
|
void
|
||||||
store_dlsch_buffer(module_id_t Mod_id,
|
store_dlsch_buffer(module_id_t Mod_id,
|
||||||
int slice_idx,
|
|
||||||
frame_t frameP,
|
frame_t frameP,
|
||||||
sub_frame_t subframeP) {
|
sub_frame_t subframeP) {
|
||||||
int UE_id, lcid;
|
|
||||||
rnti_t rnti;
|
|
||||||
mac_rlc_status_resp_t rlc_status;
|
|
||||||
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
||||||
UE_TEMPLATE *UE_template;
|
|
||||||
|
|
||||||
for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
|
for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
|
||||||
if (UE_list->active[UE_id] != TRUE)
|
if (UE_list->active[UE_id] != TRUE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx))
|
/* TODO why UE_template per CC? */
|
||||||
continue;
|
UE_TEMPLATE *UE_template = &UE_list->UE_template[UE_PCCID(Mod_id, UE_id)][UE_id];
|
||||||
|
|
||||||
UE_template = &UE_list->UE_template[UE_PCCID(Mod_id, UE_id)][UE_id];
|
|
||||||
// clear logical channel interface variables
|
|
||||||
UE_template->dl_buffer_total = 0;
|
UE_template->dl_buffer_total = 0;
|
||||||
UE_template->dl_pdus_total = 0;
|
UE_template->dl_pdus_total = 0;
|
||||||
|
|
||||||
for (lcid = 0; lcid < MAX_NUM_LCID; ++lcid) {
|
const rnti_t rnti = UE_RNTI(Mod_id, UE_id);
|
||||||
UE_template->dl_buffer_info[lcid] = 0;
|
|
||||||
UE_template->dl_pdus_in_buffer[lcid] = 0;
|
|
||||||
UE_template->dl_buffer_head_sdu_creation_time[lcid] = 0;
|
|
||||||
UE_template->dl_buffer_head_sdu_remaining_size_to_send[lcid] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rnti = UE_RNTI(Mod_id, UE_id);
|
for (int lcid = 0; lcid < MAX_NUM_LCID; ++lcid) { // loop over all the logical channels
|
||||||
|
const mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(Mod_id,
|
||||||
for (lcid = 0; lcid < MAX_NUM_LCID; ++lcid) { // loop over all the logical channels
|
rnti,
|
||||||
rlc_status = mac_rlc_status_ind(Mod_id, rnti, Mod_id, frameP, subframeP,
|
Mod_id,
|
||||||
ENB_FLAG_YES, MBMS_FLAG_NO, lcid, 0,0, 0
|
frameP,
|
||||||
);
|
subframeP,
|
||||||
|
ENB_FLAG_YES,
|
||||||
|
MBMS_FLAG_NO,
|
||||||
|
lcid,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
);
|
||||||
UE_template->dl_buffer_info[lcid] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel
|
UE_template->dl_buffer_info[lcid] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel
|
||||||
UE_template->dl_pdus_in_buffer[lcid] = rlc_status.pdus_in_buffer;
|
UE_template->dl_pdus_in_buffer[lcid] = rlc_status.pdus_in_buffer;
|
||||||
UE_template->dl_buffer_head_sdu_creation_time[lcid] = rlc_status.head_sdu_creation_time;
|
UE_template->dl_buffer_head_sdu_creation_time[lcid] = rlc_status.head_sdu_creation_time;
|
||||||
@@ -107,21 +101,20 @@ store_dlsch_buffer(module_id_t Mod_id,
|
|||||||
UE_template->dl_buffer_head_sdu_is_segmented[lcid] = rlc_status.head_sdu_is_segmented;
|
UE_template->dl_buffer_head_sdu_is_segmented[lcid] = rlc_status.head_sdu_is_segmented;
|
||||||
UE_template->dl_buffer_total += UE_template->dl_buffer_info[lcid]; //storing the total dlsch buffer
|
UE_template->dl_buffer_total += UE_template->dl_buffer_info[lcid]; //storing the total dlsch buffer
|
||||||
UE_template->dl_pdus_total += UE_template->dl_pdus_in_buffer[lcid];
|
UE_template->dl_pdus_total += UE_template->dl_pdus_in_buffer[lcid];
|
||||||
#ifdef DEBUG_eNB_SCHEDULER
|
|
||||||
|
|
||||||
|
#ifdef DEBUG_eNB_SCHEDULER
|
||||||
/* note for dl_buffer_head_sdu_remaining_size_to_send[lcid] :
|
/* note for dl_buffer_head_sdu_remaining_size_to_send[lcid] :
|
||||||
* 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent
|
* 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent
|
||||||
*/
|
*/
|
||||||
if (UE_template->dl_buffer_info[lcid] > 0)
|
if (UE_template->dl_buffer_info[lcid] > 0)
|
||||||
LOG_D(MAC,
|
LOG_D(MAC,
|
||||||
"[eNB %d][SLICE %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n",
|
"[eNB %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n",
|
||||||
Mod_id, RC.mac[Mod_id]->slice_info.dl[slice_idx].id, frameP,
|
Mod_id, frameP,
|
||||||
subframeP, UE_id, lcid, UE_template->dl_pdus_in_buffer[lcid],
|
subframeP, UE_id, lcid, UE_template->dl_pdus_in_buffer[lcid],
|
||||||
UE_template->dl_buffer_info[lcid],
|
UE_template->dl_buffer_info[lcid],
|
||||||
UE_template->dl_buffer_head_sdu_creation_time[lcid],
|
UE_template->dl_buffer_head_sdu_creation_time[lcid],
|
||||||
UE_template->dl_buffer_head_sdu_remaining_size_to_send[lcid],
|
UE_template->dl_buffer_head_sdu_remaining_size_to_send[lcid],
|
||||||
UE_template->dl_buffer_head_sdu_is_segmented[lcid]);
|
UE_template->dl_buffer_head_sdu_is_segmented[lcid]);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,102 +127,37 @@ store_dlsch_buffer(module_id_t Mod_id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cqi2mcs(int cqi) {
|
// This function returns the estimated number of RBs required to send the full
|
||||||
return cqi_to_mcs[cqi];
|
// buffer
|
||||||
|
int get_rbs_required(module_id_t Mod_id,
|
||||||
|
int CC_id,
|
||||||
|
int UE_id) {
|
||||||
|
const UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
||||||
|
|
||||||
|
if (UE_list->UE_template[CC_id][UE_id].dl_buffer_total == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const int dlsch_mcs1 = cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]];
|
||||||
|
const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id);
|
||||||
|
int nb_rbs_required = min_rb_unit;
|
||||||
|
/* calculating required number of RBs for each UE */
|
||||||
|
int TBS = get_TBS_DL(dlsch_mcs1, nb_rbs_required);
|
||||||
|
while (TBS < UE_list->UE_template[CC_id][UE_id].dl_buffer_total) {
|
||||||
|
nb_rbs_required += min_rb_unit;
|
||||||
|
TBS = get_TBS_DL(dlsch_mcs1, nb_rbs_required);
|
||||||
|
}
|
||||||
|
return nb_rbs_required;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function returns the estimated number of RBs required by each UE for downlink scheduling
|
|
||||||
void
|
void
|
||||||
assign_rbs_required(module_id_t Mod_id,
|
assign_rbs_required(module_id_t Mod_id,
|
||||||
int slice_idx,
|
int CC_id,
|
||||||
frame_t frameP,
|
uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB]) {
|
||||||
sub_frame_t subframe,
|
|
||||||
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]) {
|
|
||||||
uint16_t TBS = 0;
|
|
||||||
int UE_id, n, i, j, CC_id, pCCid, tmp;
|
|
||||||
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
||||||
slice_info_t *sli = &RC.mac[Mod_id]->slice_info;
|
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||||
eNB_UE_STATS *eNB_UE_stats, *eNB_UE_stats_i, *eNB_UE_stats_j;
|
nb_rbs_required[UE_id] = get_rbs_required(Mod_id, CC_id, UE_id);
|
||||||
int N_RB_DL;
|
// TODO: the following should not be here
|
||||||
|
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]];
|
||||||
// clear rb allocations across all CC_id
|
|
||||||
for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
|
|
||||||
if (UE_list->active[UE_id] != TRUE) continue;
|
|
||||||
|
|
||||||
if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue;
|
|
||||||
|
|
||||||
pCCid = UE_PCCID(Mod_id, UE_id);
|
|
||||||
|
|
||||||
//update CQI information across component carriers
|
|
||||||
for (n = 0; n < UE_list->numactiveCCs[UE_id]; n++) {
|
|
||||||
CC_id = UE_list->ordered_CCids[n][UE_id];
|
|
||||||
eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
|
|
||||||
// eNB_UE_stats->dlsch_mcs1 = cmin(cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]], sli->dl[slice_idx].maxmcs);
|
|
||||||
eNB_UE_stats->dlsch_mcs1 = cmin(cqi2mcs(UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]), sli->dl[slice_idx].maxmcs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// provide the list of CCs sorted according to MCS
|
|
||||||
for (i = 0; i < UE_list->numactiveCCs[UE_id]; ++i) {
|
|
||||||
eNB_UE_stats_i = &UE_list->eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]][UE_id];
|
|
||||||
|
|
||||||
for (j = i + 1; j < UE_list->numactiveCCs[UE_id]; j++) {
|
|
||||||
DevAssert(j < NFAPI_CC_MAX);
|
|
||||||
eNB_UE_stats_j = &UE_list->eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]][UE_id];
|
|
||||||
|
|
||||||
if (eNB_UE_stats_j->dlsch_mcs1 > eNB_UE_stats_i->dlsch_mcs1) {
|
|
||||||
tmp = UE_list->ordered_CCids[i][UE_id];
|
|
||||||
UE_list->ordered_CCids[i][UE_id] = UE_list->ordered_CCids[j][UE_id];
|
|
||||||
UE_list->ordered_CCids[j][UE_id] = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total > 0) {
|
|
||||||
LOG_D(MAC, "[preprocessor] assign RB for UE %d\n", UE_id);
|
|
||||||
|
|
||||||
for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) {
|
|
||||||
CC_id = UE_list->ordered_CCids[i][UE_id];
|
|
||||||
eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
|
|
||||||
const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id);
|
|
||||||
|
|
||||||
if (eNB_UE_stats->dlsch_mcs1 == 0) {
|
|
||||||
nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small
|
|
||||||
} else {
|
|
||||||
nb_rbs_required[CC_id][UE_id] = min_rb_unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rbs_required[CC_id][UE_id]);
|
|
||||||
LOG_D(MAC,
|
|
||||||
"[preprocessor] start RB assignement for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n",
|
|
||||||
UE_id, CC_id,
|
|
||||||
UE_list->UE_template[pCCid][UE_id].dl_buffer_total,
|
|
||||||
nb_rbs_required[CC_id][UE_id],
|
|
||||||
eNB_UE_stats->dlsch_mcs1, TBS);
|
|
||||||
N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
|
||||||
UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx] =
|
|
||||||
nb_rbs_allowed_slice(sli->dl[slice_idx].pct, N_RB_DL);
|
|
||||||
|
|
||||||
/* calculating required number of RBs for each UE */
|
|
||||||
while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total) {
|
|
||||||
nb_rbs_required[CC_id][UE_id] += min_rb_unit;
|
|
||||||
|
|
||||||
if (nb_rbs_required[CC_id][UE_id] > UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx]) {
|
|
||||||
TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx]);
|
|
||||||
nb_rbs_required[CC_id][UE_id] = UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rbs_required[CC_id][UE_id]);
|
|
||||||
} // end of while
|
|
||||||
|
|
||||||
LOG_D(MAC,
|
|
||||||
"[eNB %d] Frame %d: UE %d on CC %d: RB unit %d, nb_required RB %d (TBS %d, mcs %d)\n",
|
|
||||||
Mod_id, frameP, UE_id, CC_id, min_rb_unit,
|
|
||||||
nb_rbs_required[CC_id][UE_id], TBS,
|
|
||||||
eNB_UE_stats->dlsch_mcs1);
|
|
||||||
sli->pre_processor_results[slice_idx].mcs[CC_id][UE_id] = eNB_UE_stats->dlsch_mcs1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,266 +188,87 @@ maxround_ul(module_id_t Mod_id, uint16_t rnti, int sched_frame,
|
|||||||
return round_max;
|
return round_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id,
|
|
||||||
int slice_idx,
|
|
||||||
const uint8_t rbs_retx[NFAPI_CC_MAX]) {
|
|
||||||
int UE_id, CC_id, N_RB_DL, i;
|
|
||||||
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
|
||||||
UE_sched_ctrl_t *ue_sched_ctl;
|
|
||||||
uint16_t available_rbs;
|
|
||||||
|
|
||||||
for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
|
||||||
if (UE_RNTI(Mod_id, UE_id) == NOT_A_RNTI) continue;
|
|
||||||
|
|
||||||
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue;
|
|
||||||
|
|
||||||
if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue;
|
|
||||||
|
|
||||||
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
|
||||||
|
|
||||||
for (i = 0; i < UE_num_active_CC(UE_list, UE_id); ++i) {
|
|
||||||
CC_id = UE_list->ordered_CCids[i][UE_id];
|
|
||||||
N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
|
||||||
available_rbs = nb_rbs_allowed_slice(RC.mac[Mod_id]->slice_info.dl[slice_idx].pct, N_RB_DL);
|
|
||||||
|
|
||||||
if (rbs_retx[CC_id] < available_rbs)
|
|
||||||
ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_idx] = available_rbs - rbs_retx[CC_id];
|
|
||||||
else
|
|
||||||
ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_idx] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id,
|
void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id,
|
||||||
int slice_idx,
|
int CC_id,
|
||||||
frame_t frameP,
|
frame_t frameP,
|
||||||
sub_frame_t subframeP,
|
sub_frame_t subframeP,
|
||||||
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB],
|
||||||
uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]) {
|
uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB]) {
|
||||||
int UE_id, CC_id;
|
uint16_t available_rbs = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||||
int i;
|
uint8_t rbs_retx = 0;
|
||||||
rnti_t rnti;
|
uint16_t average_rbs_per_user = 0;
|
||||||
uint8_t harq_pid, round;
|
int ue_count_newtx = 0;
|
||||||
uint16_t available_rbs[NFAPI_CC_MAX];
|
int ue_count_retx = 0;
|
||||||
uint8_t rbs_retx[NFAPI_CC_MAX];
|
|
||||||
uint16_t average_rbs_per_user[NFAPI_CC_MAX];
|
|
||||||
int total_ue_count[NFAPI_CC_MAX];
|
|
||||||
int ue_count_newtx[NFAPI_CC_MAX];
|
|
||||||
int ue_count_retx[NFAPI_CC_MAX];
|
|
||||||
//uint8_t ue_retx_flag[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
|
|
||||||
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
|
||||||
UE_sched_ctrl_t *ue_sched_ctl;
|
|
||||||
COMMON_channels_t *cc;
|
|
||||||
|
|
||||||
// Reset
|
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
||||||
for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) {
|
|
||||||
total_ue_count[CC_id] = 0;
|
|
||||||
ue_count_newtx[CC_id] = 0;
|
|
||||||
ue_count_retx[CC_id] = 0;
|
|
||||||
rbs_retx[CC_id] = 0;
|
|
||||||
average_rbs_per_user[CC_id] = 0;
|
|
||||||
available_rbs[CC_id] = 0;
|
|
||||||
//for (UE_id = 0; UE_id < NFAPI_CC_MAX; ++UE_id) {
|
|
||||||
// ue_retx_flag[CC_id][UE_id] = 0;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find total UE count, and account the RBs required for retransmissions
|
// Find total UE count, and account the RBs required for retransmissions
|
||||||
for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||||
rnti = UE_RNTI(Mod_id, UE_id);
|
const rnti_t rnti = UE_RNTI(Mod_id, UE_id);
|
||||||
|
|
||||||
if (rnti == NOT_A_RNTI) continue;
|
if (rnti == NOT_A_RNTI) continue;
|
||||||
|
|
||||||
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue;
|
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue;
|
||||||
|
|
||||||
if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue;
|
const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
||||||
|
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP);
|
||||||
|
const uint8_t round = UE_list->UE_sched_ctrl[UE_id].round[CC_id][harq_pid];
|
||||||
|
|
||||||
for (i = 0; i < UE_num_active_CC(UE_list, UE_id); ++i) {
|
// retransmission
|
||||||
CC_id = UE_list->ordered_CCids[i][UE_id];
|
if (round != 8) {
|
||||||
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
nb_rbs_required[UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
|
||||||
cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
rbs_retx += nb_rbs_required[UE_id];
|
||||||
harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP);
|
ue_count_retx++;
|
||||||
round = ue_sched_ctl->round[CC_id][harq_pid];
|
} else {
|
||||||
|
ue_count_newtx++;
|
||||||
if (nb_rbs_required[CC_id][UE_id] > 0) {
|
|
||||||
total_ue_count[CC_id]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (round != 8) {
|
|
||||||
nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
|
|
||||||
rbs_retx[CC_id] += nb_rbs_required[CC_id][UE_id];
|
|
||||||
ue_count_retx[CC_id]++;
|
|
||||||
//ue_retx_flag[CC_id][UE_id] = 1;
|
|
||||||
} else {
|
|
||||||
ue_count_newtx[CC_id]++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PARTITIONING
|
available_rbs = available_rbs - rbs_retx;
|
||||||
// Reduces the available RBs according to slicing configuration
|
const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id);
|
||||||
dlsch_scheduler_pre_processor_partitioning(Mod_id, slice_idx, rbs_retx);
|
|
||||||
|
|
||||||
for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; ++CC_id) {
|
if (ue_count_newtx == 0) {
|
||||||
if (UE_list->head < 0) continue; // no UEs in list
|
average_rbs_per_user = 0;
|
||||||
|
} else if (min_rb_unit*ue_count_newtx <= available_rbs) {
|
||||||
// max_rbs_allowed_slice is saved in every UE, so take it from the first one
|
average_rbs_per_user = (uint16_t)floor(available_rbs/ue_count_newtx);
|
||||||
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_list->head];
|
} else {
|
||||||
available_rbs[CC_id] = ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_idx];
|
// consider the total number of use that can be scheduled UE
|
||||||
|
average_rbs_per_user = (uint16_t)min_rb_unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (RC.mac[Mod_id]->slice_info.dl[slice_idx].accounting) {
|
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||||
// If greedy scheduling, try to account all the required RBs
|
const rnti_t rnti = UE_RNTI(Mod_id, UE_id);
|
||||||
case POL_GREEDY:
|
|
||||||
for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
|
||||||
rnti = UE_RNTI(Mod_id, UE_id);
|
|
||||||
|
|
||||||
if (rnti == NOT_A_RNTI) continue;
|
|
||||||
|
|
||||||
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue;
|
|
||||||
|
|
||||||
if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue;
|
|
||||||
|
|
||||||
for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) {
|
|
||||||
CC_id = UE_list->ordered_CCids[i][UE_id];
|
|
||||||
|
|
||||||
if (available_rbs[CC_id] == 0) continue;
|
|
||||||
|
|
||||||
nb_rbs_accounted[CC_id][UE_id] = cmin(nb_rbs_required[CC_id][UE_id], available_rbs[CC_id]);
|
|
||||||
available_rbs[CC_id] -= nb_rbs_accounted[CC_id][UE_id];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Use the old, fair algorithm
|
|
||||||
// Loop over all active UEs and account the avg number of RBs to each UE, based on all non-retx UEs.
|
|
||||||
// case POL_FAIR:
|
|
||||||
default:
|
|
||||||
|
|
||||||
// FIXME: This is not ideal, why loop on UEs to find average_rbs_per_user[], that is per-CC?
|
|
||||||
// TODO: Look how to loop on active CCs only without using the UE_num_active_CC() function.
|
|
||||||
for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
|
||||||
rnti = UE_RNTI(Mod_id, UE_id);
|
|
||||||
|
|
||||||
if (rnti == NOT_A_RNTI) continue;
|
|
||||||
|
|
||||||
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue;
|
|
||||||
|
|
||||||
if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue;
|
|
||||||
|
|
||||||
for (i = 0; i < UE_num_active_CC(UE_list, UE_id); ++i) {
|
|
||||||
CC_id = UE_list->ordered_CCids[i][UE_id];
|
|
||||||
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
|
||||||
available_rbs[CC_id] = ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_idx];
|
|
||||||
const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id);
|
|
||||||
|
|
||||||
if (ue_count_newtx[CC_id] == 0) {
|
|
||||||
average_rbs_per_user[CC_id] = 0;
|
|
||||||
} else if (min_rb_unit*ue_count_newtx[CC_id] <= available_rbs[CC_id]) {
|
|
||||||
average_rbs_per_user[CC_id] = (uint16_t)floor(available_rbs[CC_id]/ue_count_newtx[CC_id]);
|
|
||||||
} else {
|
|
||||||
// consider the total number of use that can be scheduled UE
|
|
||||||
average_rbs_per_user[CC_id] = (uint16_t)min_rb_unit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// note: nb_rbs_required is assigned according to total_buffer_dl
|
|
||||||
// extend nb_rbs_required to capture per LCID RB required
|
|
||||||
for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
|
||||||
rnti = UE_RNTI(Mod_id, UE_id);
|
|
||||||
|
|
||||||
if (rnti == NOT_A_RNTI) continue;
|
|
||||||
|
|
||||||
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue;
|
|
||||||
|
|
||||||
if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue;
|
|
||||||
|
|
||||||
for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) {
|
|
||||||
CC_id = UE_list->ordered_CCids[i][UE_id];
|
|
||||||
nb_rbs_accounted[CC_id][UE_id] = cmin(average_rbs_per_user[CC_id], nb_rbs_required[CC_id][UE_id]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check retransmissions
|
|
||||||
// TODO: Do this once at the beginning
|
|
||||||
for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
|
||||||
rnti = UE_RNTI(Mod_id, UE_id);
|
|
||||||
|
|
||||||
if (rnti == NOT_A_RNTI) continue;
|
if (rnti == NOT_A_RNTI) continue;
|
||||||
|
|
||||||
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue;
|
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue;
|
||||||
|
|
||||||
if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue;
|
const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
||||||
|
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP);
|
||||||
|
const uint8_t round = UE_list->UE_sched_ctrl[UE_id].round[CC_id][harq_pid];
|
||||||
|
|
||||||
for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) {
|
/* TODO the first seems unnecessary, remove it */
|
||||||
CC_id = UE_list->ordered_CCids[i][UE_id];
|
if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED || round != 8)
|
||||||
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
nb_rbs_accounted[UE_id] = nb_rbs_required[UE_id];
|
||||||
cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
else
|
||||||
harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP);
|
nb_rbs_accounted[UE_id] = cmin(average_rbs_per_user, nb_rbs_required[UE_id]);
|
||||||
round = ue_sched_ctl->round[CC_id][harq_pid];
|
|
||||||
|
|
||||||
// control channel or retransmission
|
|
||||||
/* TODO: do we have to check for retransmission? */
|
|
||||||
if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED || round != 8) {
|
|
||||||
nb_rbs_accounted[CC_id][UE_id] = nb_rbs_required[CC_id][UE_id];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id,
|
void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id,
|
||||||
int slice_idx,
|
int CC_id,
|
||||||
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB],
|
||||||
uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB],
|
||||||
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
uint8_t rballoc_sub[N_RBG_MAX]) {
|
||||||
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) {
|
|
||||||
int UE_id, CC_id;
|
|
||||||
int i;
|
|
||||||
int N_RBG[NFAPI_CC_MAX];
|
|
||||||
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
||||||
|
|
||||||
for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) {
|
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||||
COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
|
||||||
N_RBG[CC_id] = to_rbg(cc->mib->message.dl_Bandwidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to allocate accounted RBs
|
|
||||||
for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
|
||||||
if (UE_RNTI(Mod_id, UE_id) == NOT_A_RNTI) continue;
|
if (UE_RNTI(Mod_id, UE_id) == NOT_A_RNTI) continue;
|
||||||
|
|
||||||
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue;
|
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue;
|
||||||
|
|
||||||
if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue;
|
dlsch_scheduler_pre_processor_allocate(Mod_id,
|
||||||
|
UE_id,
|
||||||
|
CC_id,
|
||||||
|
nb_rbs_required[UE_id],
|
||||||
|
&nb_rbs_accounted[UE_id],
|
||||||
|
rballoc_sub);
|
||||||
|
|
||||||
for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) {
|
|
||||||
CC_id = UE_list->ordered_CCids[i][UE_id];
|
|
||||||
nb_rbs_remaining[CC_id][UE_id] = nb_rbs_accounted[CC_id][UE_id];
|
|
||||||
|
|
||||||
if (nb_rbs_required[CC_id][UE_id] > 0)
|
|
||||||
LOG_D(MAC,
|
|
||||||
"Step 1: nb_rbs_remaining[%d][%d]= %d (accounted %d, required %d, pre_nb_available_rbs %d, N_RBG %d)\n",
|
|
||||||
CC_id,
|
|
||||||
UE_id,
|
|
||||||
nb_rbs_remaining[CC_id][UE_id],
|
|
||||||
nb_rbs_accounted[CC_id][UE_id],
|
|
||||||
nb_rbs_required[CC_id][UE_id],
|
|
||||||
UE_list->UE_sched_ctrl[UE_id].pre_nb_available_rbs[CC_id],
|
|
||||||
N_RBG[CC_id]);
|
|
||||||
|
|
||||||
LOG_T(MAC, "calling dlsch_scheduler_pre_processor_allocate .. \n ");
|
|
||||||
dlsch_scheduler_pre_processor_allocate(Mod_id,
|
|
||||||
UE_id,
|
|
||||||
CC_id,
|
|
||||||
N_RBG[CC_id],
|
|
||||||
nb_rbs_required,
|
|
||||||
nb_rbs_remaining,
|
|
||||||
rballoc_sub);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,91 +278,66 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
|
|||||||
int CC_id,
|
int CC_id,
|
||||||
frame_t frameP,
|
frame_t frameP,
|
||||||
sub_frame_t subframeP) {
|
sub_frame_t subframeP) {
|
||||||
int UE_id;
|
uint8_t rballoc_sub[N_RBG_MAX];
|
||||||
uint16_t i, j;
|
|
||||||
int slice_idx = 0;
|
|
||||||
// TODO: remove NFAPI_CC_MAX, here for compatibility for the moment
|
|
||||||
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX];
|
|
||||||
memset(rballoc_sub, 0, sizeof(rballoc_sub));
|
memset(rballoc_sub, 0, sizeof(rballoc_sub));
|
||||||
|
|
||||||
eNB_MAC_INST *eNB = RC.mac[Mod_id];
|
|
||||||
slice_info_t *sli = &eNB->slice_info;
|
|
||||||
uint16_t (*nb_rbs_required)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_required;
|
|
||||||
uint16_t (*nb_rbs_accounted)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_accounted;
|
|
||||||
uint16_t (*nb_rbs_remaining)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_remaining;
|
|
||||||
|
|
||||||
UE_list_t *UE_list = &eNB->UE_list;
|
|
||||||
UE_sched_ctrl_t *ue_sched_ctl;
|
|
||||||
|
|
||||||
// Initialize scheduling information for all active UEs
|
// Initialize scheduling information for all active UEs
|
||||||
memset(&sli->pre_processor_results[slice_idx], 0, sizeof(sli->pre_processor_results[slice_idx]));
|
|
||||||
dlsch_scheduler_pre_processor_reset(Mod_id,
|
dlsch_scheduler_pre_processor_reset(Mod_id,
|
||||||
CC_id,
|
CC_id,
|
||||||
rballoc_sub[CC_id]);
|
rballoc_sub);
|
||||||
// STATUS
|
|
||||||
// Store the DLSCH buffer for each logical channel
|
|
||||||
store_dlsch_buffer(Mod_id,
|
store_dlsch_buffer(Mod_id,
|
||||||
slice_idx,
|
|
||||||
frameP,
|
frameP,
|
||||||
subframeP);
|
subframeP);
|
||||||
|
|
||||||
// Calculate the number of RBs required by each UE on the basis of logical channel's buffer
|
// Calculate the number of RBs required by each UE on the basis of logical channel's buffer
|
||||||
|
uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB];
|
||||||
|
memset(nb_rbs_required, 0, sizeof(nb_rbs_required));
|
||||||
assign_rbs_required(Mod_id,
|
assign_rbs_required(Mod_id,
|
||||||
slice_idx,
|
CC_id,
|
||||||
frameP,
|
|
||||||
subframeP,
|
|
||||||
nb_rbs_required);
|
nb_rbs_required);
|
||||||
|
|
||||||
// ACCOUNTING
|
|
||||||
// This procedure decides the number of RBs to allocate
|
// Decide the number of RBs to allocate
|
||||||
|
uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB];
|
||||||
|
memset(nb_rbs_accounted, 0, sizeof(nb_rbs_accounted));
|
||||||
dlsch_scheduler_pre_processor_accounting(Mod_id,
|
dlsch_scheduler_pre_processor_accounting(Mod_id,
|
||||||
slice_idx,
|
CC_id,
|
||||||
frameP,
|
frameP,
|
||||||
subframeP,
|
subframeP,
|
||||||
nb_rbs_required,
|
nb_rbs_required,
|
||||||
nb_rbs_accounted);
|
nb_rbs_accounted);
|
||||||
|
|
||||||
// POSITIONING
|
// POSITIONING
|
||||||
// This procedure does the main allocation of the RBs
|
// This procedure does the main allocation of the RBs
|
||||||
dlsch_scheduler_pre_processor_positioning(Mod_id,
|
dlsch_scheduler_pre_processor_positioning(Mod_id,
|
||||||
slice_idx,
|
CC_id,
|
||||||
nb_rbs_required,
|
nb_rbs_required,
|
||||||
nb_rbs_accounted,
|
nb_rbs_accounted,
|
||||||
nb_rbs_remaining,
|
|
||||||
rballoc_sub);
|
rballoc_sub);
|
||||||
|
|
||||||
|
const UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
||||||
|
const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
||||||
|
const int N_RBG = to_rbg(cc->mib->message.dl_Bandwidth);
|
||||||
|
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||||
|
const UE_sched_ctrl_t *ue_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
|
||||||
|
|
||||||
for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0)
|
||||||
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) {
|
char s[101];
|
||||||
CC_id = UE_list->ordered_CCids[i][UE_id];
|
for (int i = 0; i < N_RBG; i++)
|
||||||
//PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id];
|
sprintf(&s[i*2], " %d", ue_sched_ctrl->rballoc_sub_UE[CC_id][i]);
|
||||||
COMMON_channels_t *cc = &eNB->common_channels[CC_id];
|
|
||||||
int N_RBG = to_rbg(cc->mib->message.dl_Bandwidth);
|
|
||||||
|
|
||||||
if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0) {
|
LOG_D(MAC,
|
||||||
LOG_D(MAC, "******************DL Scheduling Information for UE%d ************************\n",
|
"%d/%d allocation UE %d RNTI %x:%s, total %d, MCS %d\n",
|
||||||
UE_id);
|
frameP,
|
||||||
LOG_D(MAC, "dl power offset UE%d = %d \n",
|
subframeP,
|
||||||
UE_id,
|
UE_id,
|
||||||
ue_sched_ctl->dl_pow_off[CC_id]);
|
UE_list->UE_template[CC_id][UE_id].rnti,
|
||||||
LOG_D(MAC, "***********RB Alloc for every subband for UE%d ***********\n",
|
s,
|
||||||
UE_id);
|
ue_sched_ctrl->pre_nb_available_rbs[CC_id],
|
||||||
|
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1);
|
||||||
for (j = 0; j < N_RBG; j++) {
|
|
||||||
//PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[UE_id] = rballoc_sub_UE[CC_id][UE_id][UE_id];
|
|
||||||
LOG_D(MAC, "RB Alloc for UE%d and Subband%d = %d\n",
|
|
||||||
UE_id, j,
|
|
||||||
ue_sched_ctl->rballoc_sub_UE[CC_id][j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id];
|
|
||||||
LOG_D(MAC, "[eNB %d][SLICE %d]Total RBs allocated for UE%d = %d\n",
|
|
||||||
Mod_id,
|
|
||||||
eNB->slice_info.dl[slice_idx].id,
|
|
||||||
UE_id,
|
|
||||||
ue_sched_ctl->pre_nb_available_rbs[CC_id]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,43 +386,37 @@ void
|
|||||||
dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id,
|
dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id,
|
||||||
int UE_id,
|
int UE_id,
|
||||||
uint8_t CC_id,
|
uint8_t CC_id,
|
||||||
int N_RBG,
|
uint16_t nb_rbs_required,
|
||||||
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
uint16_t *nb_rbs_remaining,
|
||||||
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
|
uint8_t rballoc_sub[N_RBG_MAX]) {
|
||||||
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) {
|
UE_sched_ctrl_t *ue_sched_ctl = &RC.mac[Mod_id]->UE_list.UE_sched_ctrl[UE_id];
|
||||||
int i;
|
const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||||
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
const int N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||||
UE_sched_ctrl_t *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
|
||||||
int N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
|
||||||
const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id);
|
const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id);
|
||||||
|
|
||||||
for (i = 0; i < N_RBG; i++) {
|
for (int i = 0; i < N_RBG; i++) {
|
||||||
if (rballoc_sub[CC_id][i] != 0) continue;
|
if (rballoc_sub[i] != 0) continue;
|
||||||
|
|
||||||
if (ue_sched_ctl->rballoc_sub_UE[CC_id][i] != 0) continue;
|
if (ue_sched_ctl->rballoc_sub_UE[CC_id][i] != 0) continue;
|
||||||
|
if (*nb_rbs_remaining <= 0) continue;
|
||||||
if (nb_rbs_remaining[CC_id][UE_id] <= 0) continue;
|
if (ue_sched_ctl->pre_nb_available_rbs[CC_id] >= nb_rbs_required) continue;
|
||||||
|
|
||||||
if (ue_sched_ctl->pre_nb_available_rbs[CC_id] >= nb_rbs_required[CC_id][UE_id]) continue;
|
|
||||||
|
|
||||||
if (ue_sched_ctl->dl_pow_off[CC_id] == 0) continue;
|
if (ue_sched_ctl->dl_pow_off[CC_id] == 0) continue;
|
||||||
|
|
||||||
if ((i == N_RBG - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) {
|
if ((i == N_RBG - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) {
|
||||||
// Allocating last, smaller RBG
|
// Allocating last, smaller RBG
|
||||||
if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit - 1) {
|
if (*nb_rbs_remaining >= min_rb_unit - 1) {
|
||||||
rballoc_sub[CC_id][i] = 1;
|
rballoc_sub[i] = 1;
|
||||||
ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
|
ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
|
||||||
|
|
||||||
nb_rbs_remaining[CC_id][UE_id] = nb_rbs_remaining[CC_id][UE_id] - min_rb_unit + 1;
|
*nb_rbs_remaining -= min_rb_unit + 1;
|
||||||
ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1;
|
ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Allocating a standard-sized RBG
|
// Allocating a standard-sized RBG
|
||||||
if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit) {
|
if (*nb_rbs_remaining >= min_rb_unit) {
|
||||||
rballoc_sub[CC_id][i] = 1;
|
rballoc_sub[i] = 1;
|
||||||
ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
|
ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
|
||||||
|
|
||||||
nb_rbs_remaining[CC_id][UE_id] = nb_rbs_remaining[CC_id][UE_id] - min_rb_unit;
|
*nb_rbs_remaining -= min_rb_unit;
|
||||||
ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit;
|
ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user