From 17cbc4dbf4c347b5dd3f0383f0c4130533dbd14b Mon Sep 17 00:00:00 2001 From: Robert Schmidt <robert.schmidt@openairinterface.org> Date: Fri, 21 Jan 2022 16:55:14 +0100 Subject: [PATCH] Generalize get_mcs_from_bler() --- openair2/GNB_APP/MACRLC_nr_paramdef.h | 12 ++- openair2/GNB_APP/gnb_config.c | 8 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 81 ++----------------- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 45 +++++++++++ openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 6 ++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 21 ++--- 6 files changed, 77 insertions(+), 96 deletions(-) diff --git a/openair2/GNB_APP/MACRLC_nr_paramdef.h b/openair2/GNB_APP/MACRLC_nr_paramdef.h index e634f077e26..b7c8401971f 100644 --- a/openair2/GNB_APP/MACRLC_nr_paramdef.h +++ b/openair2/GNB_APP/MACRLC_nr_paramdef.h @@ -62,7 +62,6 @@ #define CONFIG_STRING_MACRLC_PUSCHFAILURETHRES "pusch_FailureThres" #define CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER "dl_bler_target_upper" #define CONFIG_STRING_MACRLC_DL_BLER_TARGET_LOWER "dl_bler_target_lower" -#define CONFIG_STRING_MACRLC_DL_RD2_BLER_THRESHOLD "dl_rd2_bler_threshold" #define CONFIG_STRING_MACRLC_DL_MAX_MCS "dl_max_mcs" #define CONFIG_STRING_MACRLC_HARQ_ROUND_MAX "harq_round_max" #define CONFIG_STRING_MACRLC_MIN_GRANT_PRB "min_grant_prb" @@ -97,7 +96,6 @@ {CONFIG_STRING_MACRLC_PUSCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER, "Upper threshold of BLER to decrease DL MCS", 0, dblptr:NULL, defdblval:0.15, TYPE_DOUBLE, 0}, \ {CONFIG_STRING_MACRLC_DL_BLER_TARGET_LOWER, "Lower threshold of BLER to increase DL MCS", 0, dblptr:NULL, defdblval:0.05, TYPE_DOUBLE, 0}, \ -{CONFIG_STRING_MACRLC_DL_RD2_BLER_THRESHOLD, "Threshold of RD2/RETX2 BLER to decrease DL MCS", 0, dblptr:NULL, defdblval:0.01, TYPE_DOUBLE, 0}, \ {CONFIG_STRING_MACRLC_DL_MAX_MCS, "Maximum DL MCS that should be used", 0, u8ptr:NULL, defintval:28, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_HARQ_ROUND_MAX, "Maximum number of HARQ rounds", 0, u8ptr:NULL, defintval:4, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_MIN_GRANT_PRB, "Minimal Periodic ULSCH Grant PRBs", 0, u8ptr:NULL, defintval:5, TYPE_UINT8, 0}, \ @@ -127,10 +125,10 @@ #define MACRLC_PUSCHFAILURETHRES_IDX 21 #define MACRLC_DL_BLER_TARGET_UPPER_IDX 22 #define MACRLC_DL_BLER_TARGET_LOWER_IDX 23 -#define MACRLC_DL_RD2_BLER_THRESHOLD_IDX 24 -#define MACRLC_DL_MAX_MCS_IDX 25 -#define MACRLC_HARQ_ROUND_MAX_IDX 26 -#define MACRLC_MIN_GRANT_PRB_IDX 27 -#define MACRLC_MIN_GRANT_MCS_IDX 28 +#define MACRLC_DL_MAX_MCS_IDX 24 +#define MACRLC_HARQ_ROUND_MAX_IDX 25 +#define MACRLC_MIN_GRANT_PRB_IDX 26 +#define MACRLC_MIN_GRANT_MCS_IDX 27 + /*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ #endif diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index c11d6b80923..f57402c1843 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -873,10 +873,10 @@ void RCconfig_nr_macrlc() { AssertFatal(1==0,"MACRLC %d: %s unknown southbound midhaul\n",j,*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr)); } RC.nrmac[j]->ulsch_max_frame_inactivity = *(MacRLC_ParamList.paramarray[j][MACRLC_ULSCH_MAX_FRAME_INACTIVITY].uptr); - RC.nrmac[j]->dl_bler_target_upper = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_UPPER_IDX].dblptr); - RC.nrmac[j]->dl_bler_target_lower = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_LOWER_IDX].dblptr); - RC.nrmac[j]->dl_rd2_bler_threshold = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_RD2_BLER_THRESHOLD_IDX].dblptr); - RC.nrmac[j]->dl_max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_MAX_MCS_IDX].u8ptr); + NR_bler_options_t *dl_bler_options = &RC.nrmac[j]->dl_bler; + dl_bler_options->upper = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_UPPER_IDX].dblptr); + dl_bler_options->lower = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_LOWER_IDX].dblptr); + dl_bler_options->max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_MAX_MCS_IDX].u8ptr); RC.nrmac[j]->harq_round_max = *(MacRLC_ParamList.paramarray[j][MACRLC_HARQ_ROUND_MAX_IDX].u8ptr); RC.nrmac[j]->min_grant_prb = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_PRB_IDX].u8ptr); RC.nrmac[j]->min_grant_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_MCS_IDX].u8ptr); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 3a179fbaea1..30127847dc8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -397,79 +397,6 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, return offset; } -#define BLER_UPDATE_FRAME 10 -#define BLER_FILTER 0.9f -int get_mcs_from_bler(module_id_t mod_id, int CC_id, frame_t frame, sub_frame_t slot, int UE_id, int mcs_table) { - gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; - const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; - const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - int max_allowed_mcs = (mcs_table == 1) ? 27 : 28; - - NR_UE_sched_ctrl_t *sched_ctrl = &nrmac->UE_info.UE_sched_ctrl[UE_id]; - NR_DL_bler_stats_t *bler_stats = &sched_ctrl->dl_bler_stats; - /* first call: everything is zero. Initialize to sensible default */ - if (bler_stats->last_frame_slot == 0 && bler_stats->mcs == 0) { - bler_stats->last_frame_slot = frame * n + slot; - bler_stats->mcs = 9; - bler_stats->bler = (nrmac->dl_bler_target_lower + nrmac->dl_bler_target_upper) / 2; - bler_stats->rd2_bler = nrmac->dl_rd2_bler_threshold; - } - - const int now = frame * n + slot; - int diff = now - bler_stats->last_frame_slot; - - if (diff < 0) // wrap around - diff += 1024 * n; - - const uint8_t old_mcs = bler_stats->mcs; - const NR_mac_stats_t *stats = &nrmac->UE_info.mac_stats[UE_id]; - - // TODO put back this condition when relevant - /*const int dret3x = stats->dl.rounds[3] - bler_stats->dlsch_rounds[3]; - if (dret3x > 0) { - if there is a third retransmission, decrease MCS for stabilization and - restart averaging window to stabilize transmission - bler_stats->last_frame_slot = now; - bler_stats->mcs = max(9, bler_stats->mcs - 1); - memcpy(bler_stats->dlsch_rounds, stats->dl.rounds, sizeof(stats->dl.rounds)); - LOG_D(MAC, "%4d.%2d: %d retx in 3rd round, setting MCS to %d and restarting window\n", frame, slot, dret3x, bler_stats->mcs); - return bler_stats->mcs; - }*/ - if (diff < BLER_UPDATE_FRAME * n) - return old_mcs; // no update - - // last update is longer than x frames ago - const int dtx = (int)(stats->dl.rounds[0] - bler_stats->dlsch_rounds[0]); - const int dretx = (int)(stats->dl.rounds[1] - bler_stats->dlsch_rounds[1]); - const int dretx2 = (int)(stats->dl.rounds[2] - bler_stats->dlsch_rounds[2]); - const float bler_window = dtx > 0 ? (float) dretx / dtx : bler_stats->bler; - const float rd2_bler_wnd = dtx > 0 ? (float) dretx2 / dtx : bler_stats->rd2_bler; - bler_stats->bler = BLER_FILTER * bler_stats->bler + (1 - BLER_FILTER) * bler_window; - bler_stats->rd2_bler = BLER_FILTER / 4 * bler_stats->rd2_bler + (1 - BLER_FILTER / 4) * rd2_bler_wnd; - int new_mcs = old_mcs; - - // TODO put back this condition when relevant - /* first ensure that number of 2nd retx is below threshold. If this is the - * case, use 1st retx to adjust faster - if (bler_stats->rd2_bler > nrmac->dl_rd2_bler_threshold && old_mcs > 6) { - new_mcs -= 2; - } else if (bler_stats->rd2_bler < nrmac->dl_rd2_bler_threshold) {*/ - const int max_mcs = min(max_allowed_mcs, min(sched_ctrl->dl_max_mcs, nrmac->dl_max_mcs)); - if (bler_stats->bler < nrmac->dl_bler_target_lower && old_mcs < max_mcs && dtx > 9) - new_mcs += 1; - else if ((bler_stats->bler > nrmac->dl_bler_target_upper && old_mcs > 6) // above threshold - || (dtx <= 3 && old_mcs > 9)) // no activity - new_mcs -= 1; - - // else we are within threshold boundaries - bler_stats->last_frame_slot = now; - bler_stats->mcs = new_mcs; - memcpy(bler_stats->dlsch_rounds, stats->dl.rounds, sizeof(stats->dl.rounds)); - LOG_D(MAC, "%4d.%2d MCS %d -> %d (dtx %d, dretx %d, BLER wnd %.3f avg %.6f, dretx2 %d, RD2 BLER wnd %.3f avg %.6f)\n", - frame, slot, old_mcs, new_mcs, dtx, dretx, bler_window, bler_stats->bler, dretx2, rd2_bler_wnd, bler_stats->rd2_bler); - return new_mcs; -} - void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_frame_t slot) { @@ -740,6 +667,7 @@ void pf_dl(module_id_t module_id, if (sched_ctrl->ul_failure==1 && get_softmodem_params()->phy_test==0) continue; + const NR_mac_dir_stats_t *stats = &UE_info->mac_stats[UE_id].dl; NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ @@ -747,7 +675,7 @@ void pf_dl(module_id_t module_id, layers[UE_id] = ps->nrOfLayers; // initialization of layers to the previous value in the strcuture /* Calculate Throughput */ const float a = 0.0005f; // corresponds to 200ms window - const uint32_t b = UE_info->mac_stats[UE_id].dl.current_bytes; + const uint32_t b = stats->current_bytes; thr_ue[UE_id] = (1 - a) * thr_ue[UE_id] + a * b; /* retransmission */ @@ -770,7 +698,10 @@ void pf_dl(module_id_t module_id, continue; /* Calculate coeff */ - sched_pdsch->mcs = get_mcs_from_bler(module_id, /* CC_id = */ 0, frame, slot, UE_id, ps->mcsTableIdx); + const NR_bler_options_t *bo = &mac->dl_bler; + const int max_mcs_table = ps->mcsTableIdx == 1 ? 27 : 28; + const int max_mcs = min(sched_ctrl->dl_max_mcs, max_mcs_table); + sched_pdsch->mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->dl_bler_stats, max_mcs, frame); layers[UE_id] = set_dl_nrOfLayers(sched_ctrl); const uint8_t Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx); const uint16_t R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 09b890a8606..933dee8be47 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -761,6 +761,51 @@ void nr_set_pusch_semi_static(const NR_SIB1_t *sib1, : num_dmrs_cdm_grps_no_data * 4; } +#define BLER_UPDATE_FRAME 10 +#define BLER_FILTER 0.9f +int get_mcs_from_bler(const NR_bler_options_t *bler_options, + const NR_mac_dir_stats_t *stats, + NR_bler_stats_t *bler_stats, + int max_mcs, + frame_t frame) +{ + /* first call: everything is zero. Initialize to sensible default */ + if (bler_stats->last_frame == 0 && bler_stats->mcs == 0) { + bler_stats->last_frame = frame; + bler_stats->mcs = 9; + bler_stats->bler = (bler_options->lower + bler_options->upper) / 2.0f; + } + int diff = frame - bler_stats->last_frame; + if (diff < 0) // wrap around + diff += 1024; + + max_mcs = min(max_mcs, bler_options->max_mcs); + const uint8_t old_mcs = min(bler_stats->mcs, max_mcs); + if (diff < BLER_UPDATE_FRAME) + return old_mcs; // no update + + // last update is longer than x frames ago + const int dtx = (int)(stats->rounds[0] - bler_stats->rounds[0]); + const int dretx = (int)(stats->rounds[1] - bler_stats->rounds[1]); + const float bler_window = dtx > 0 ? (float) dretx / dtx : bler_stats->bler; + bler_stats->bler = BLER_FILTER * bler_stats->bler + (1 - BLER_FILTER) * bler_window; + + int new_mcs = old_mcs; + if (bler_stats->bler < bler_options->lower && old_mcs < max_mcs && dtx > 9) + new_mcs += 1; + else if ((bler_stats->bler > bler_options->upper && old_mcs > 6) // above threshold + || (dtx <= 3 && old_mcs > 9)) // no activity + new_mcs -= 1; + // else we are within threshold boundaries + + bler_stats->last_frame = frame; + bler_stats->mcs = new_mcs; + memcpy(bler_stats->rounds, stats->rounds, sizeof(stats->rounds)); + LOG_D(MAC, "frame %4d MCS %d -> %d (dtx %d, dretx %d, BLER wnd %.3f avg %.6f)\n", + frame, old_mcs, new_mcs, dtx, dretx, bler_window, bler_stats->bler); + return new_mcs; +} + void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu, nr_scs_e scs_common, nr_scs_e pdcch_scs, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index cdb1658f55b..f645bc91482 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -535,6 +535,12 @@ bool nr_find_nb_rb(uint16_t Qm, uint32_t *tbs, uint16_t *nb_rb); +int get_mcs_from_bler(const NR_bler_options_t *bler_options, + const NR_mac_dir_stats_t *stats, + NR_bler_stats_t *bler_stats, + int max_mcs, + frame_t frame); + void nr_sr_reporting(int Mod_idP, frame_t frameP, sub_frame_t slotP); void dump_mac_stats(gNB_MAC_INST *gNB, char *output, int strlen, bool reset_rsrp); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 6f5f7b3d957..33fe7c8bda9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -459,13 +459,12 @@ typedef struct NR_UE_harq { //! fixme : need to enhace for the multiple TB CQI report -typedef struct NR_DL_bler_stats { - frame_t last_frame_slot; +typedef struct NR_bler_stats { + frame_t last_frame; float bler; - float rd2_bler; uint8_t mcs; - uint64_t dlsch_rounds[8]; -} NR_DL_bler_stats_t; + uint64_t rounds[8]; +} NR_bler_stats_t; // /*! As per spec 38.214 section 5.2.1.4.2 @@ -627,7 +626,7 @@ typedef struct { mac_rlc_status_resp_t rlc_status[NR_MAX_NUM_LCID]; /// Estimation of HARQ from BLER - NR_DL_bler_stats_t dl_bler_stats; + NR_bler_stats_t dl_bler_stats; uint16_t ta_frame; int16_t ta_update; @@ -694,6 +693,11 @@ typedef struct NR_mac_stats { uint8_t num_rsrp_meas; } NR_mac_stats_t; +typedef struct NR_bler_options { + double upper; + double lower; + uint8_t max_mcs; +} NR_bler_options_t; /*! \brief UE list used by gNB to order UEs/CC for scheduling*/ #define MAX_CSI_REPORTCONFIG 48 @@ -835,10 +839,7 @@ typedef struct gNB_MAC_INST_s { int xp_pdsch_antenna_ports; bool first_MIB; - double dl_bler_target_upper; - double dl_bler_target_lower; - double dl_rd2_bler_threshold; - uint8_t dl_max_mcs; + NR_bler_options_t dl_bler; uint8_t harq_round_max; uint8_t min_grant_prb; uint8_t min_grant_mcs; -- GitLab