diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 3d2d1254bf..2ad1d384a2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -248,6 +248,38 @@ uint16_t get_pm_index(const gNB_MAC_INST *nrmac, } } +// look-up table for AMC. Based on BLER vs SNR curves from the nr_dlsim simulation +// command line: nr_dlsim -n 10000 -m 0 -R 25 -b 25 -e MCS -s START_SNR -t 99.99 +// SNR Thresholds for MCS=[0,...,28]; START_SNR=chosen values with a resolution of 0.2dB to maintain a BLER of 10^-3 +static const int SINRx10_MCS_mapping[29] = { + -10, -4, 6, 16, 24, 34, 42, 50, 56, 62, // 0..9 + 86, 92, 98, 104, 112, 118, 124, 140, 146, 154, // 10..19 + 162, 170, 178, 186, 194, 202, 212, 220, 245 // 20..28 +}; + +int get_mcs_from_SINRx10(int mcs_table, int SINRx10, int Nl) +{ + if (mcs_table != 0) { + LOG_E(MAC, "mcs_table = %d, but get_mcs_from_SINRx10() only supports MCS table 0 (TS 38.214 - Table 5.1.3.1-1)\n", mcs_table); + return 28; + } + + int MIMO_SNRx10 = 0; + if (Nl == 2) + MIMO_SNRx10 = 40; + else if (Nl == 4) + MIMO_SNRx10 = 70; + + for (int i = 28; i >= 0; i--) { + if (SINRx10 >= SINRx10_MCS_mapping[i] + MIMO_SNRx10) + return i; + } + + LOG_W(MAC, "SINR (%d.%d dB) too low, no MCS possible to achieve BLER of 10^-3\n", SINRx10 / 10, SINRx10 % 10); + + return 0; +} + uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx) { if (cqi_idx <= 0) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index f2a1988459..9e0cba1cdd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -539,7 +539,11 @@ static void evaluate_sinr_report(gNB_MAC_INST *nrmac, stats->cumul_sinrx10 += sinr_report->SINRx10[0]; stats->num_sinr_meas++; - LOG_D(MAC, "Reported SSB-SINR = %d.%d\n", sinr_report->SINRx10[0] / 10, sinr_report->SINRx10[0] % 10); + const int mcs_table = UE->current_DL_BWP.mcsTableIdx; + const int nrOfLayers = get_dl_nrOfLayers(sched_ctrl, UE->current_DL_BWP.dci_format); + sched_ctrl->dl_max_mcs = get_mcs_from_SINRx10(mcs_table, sinr_report->SINRx10[0], nrOfLayers); + + LOG_D(MAC, "Reported SSB-SINR = %d.%d, dl_max_mcs %d\n", sinr_report->SINRx10[0] / 10, sinr_report->SINRx10[0] % 10, sched_ctrl->dl_max_mcs); } static void evaluate_rsrp_report(gNB_MAC_INST *nrmac, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 84a0923e8b..78c6485a3c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -403,6 +403,7 @@ uint16_t get_pm_index(const gNB_MAC_INST *nrmac, int layers, int xp_pdsch_antenna_ports); +int get_mcs_from_SINRx10(int mcs_table, int SINRx10, int Nl); 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);