Merge remote-tracking branch 'origin/sinr_based_amc' into integration_2025_w37 (!3601)
gNB: adaptive DL/UL MCS based on reported SSB-SINR and measured PUSCH SNR Currently this is used esp. if the number of rounds is limited to 1 (e.g. disable_harq).
This commit is contained in:
@@ -683,7 +683,8 @@ static void pf_dl(module_id_t module_id,
|
||||
const int max_mcs_table = current_BWP->mcsTableIdx == 1 ? 27 : 28;
|
||||
const int max_mcs = min(sched_ctrl->dl_max_mcs, max_mcs_table);
|
||||
if (bo->harq_round_max == 1) {
|
||||
sched_pdsch->mcs = min(bo->max_mcs, max_mcs);
|
||||
int new_mcs = min(bo->max_mcs, max_mcs);
|
||||
sched_pdsch->mcs = max(bo->min_mcs, new_mcs);
|
||||
sched_ctrl->dl_bler_stats.mcs = sched_pdsch->mcs;
|
||||
} else
|
||||
sched_pdsch->mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->dl_bler_stats, max_mcs, frame);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -414,6 +414,25 @@ static void handle_dl_harq(NR_UE_info_t * UE,
|
||||
}
|
||||
}
|
||||
|
||||
// Referred Table 10.1.16.1-1 in 38.133 V16.7.0.
|
||||
static int get_measured_sinr(int index)
|
||||
{
|
||||
if (index < 0 || index > 127)
|
||||
return INT_MAX;
|
||||
|
||||
return -235 + index * 5;
|
||||
}
|
||||
|
||||
// Referred Table 10.1.16.1-2 in 38.133 V16.7.0.
|
||||
static int get_diff_sinr(int index, int best_SINRx10)
|
||||
{
|
||||
if (index <= 0)
|
||||
return best_SINRx10;
|
||||
if (index >= 15)
|
||||
return best_SINRx10 - 150;
|
||||
return best_SINRx10 - index * 10;
|
||||
}
|
||||
|
||||
//returns the measured RSRP value (upper limit)
|
||||
static bool get_measured_rsrp(uint8_t index, int *rsrp)
|
||||
{
|
||||
@@ -498,22 +517,33 @@ static void evaluate_sinr_report(gNB_MAC_INST *nrmac,
|
||||
}
|
||||
|
||||
curr_payload = pickandreverse_bits(payload, 7, *cumul_bits);
|
||||
sinr_report->SINR_index[0] = curr_payload & 0x7f;
|
||||
int sinr_index = curr_payload & 0x7f;
|
||||
*cumul_bits += 7;
|
||||
|
||||
csi_report->nb_of_csi_ssb_report++;
|
||||
if (sinr_report->SINR_index[0] < 0 || sinr_report->SINR_index[0] > 127) {
|
||||
LOG_E(NR_MAC, "UE %04x: reported SINR index %d invalid\n", UE->rnti, sinr_report->SINR_index[0]);
|
||||
int SINRx10 = get_measured_sinr(sinr_index);
|
||||
if (SINRx10 == INT_MAX) {
|
||||
LOG_E(NR_MAC, "UE %04x: reported SINR index %d invalid\n", UE->rnti, sinr_index);
|
||||
return;
|
||||
}
|
||||
sinr_report->SINRx10[0] = SINRx10;
|
||||
|
||||
for (int i = 1; i < sinr_report->nr_reports; i++) {
|
||||
curr_payload = pickandreverse_bits(payload, 4, *cumul_bits);
|
||||
sinr_report->SINR_index[i] = curr_payload & 0x0f;
|
||||
sinr_report->SINRx10[i] = get_diff_sinr(curr_payload & 0x0f, sinr_report->SINRx10[0]);
|
||||
*cumul_bits += 4;
|
||||
}
|
||||
|
||||
LOG_D(MAC, "Reported SSB-SINR index = %d\n", sinr_report->SINR_index[0]);
|
||||
NR_mac_stats_t *stats = &UE->mac_stats;
|
||||
// including ssb SINR in mac stats
|
||||
stats->cumul_sinrx10 += sinr_report->SINRx10[0];
|
||||
stats->num_sinr_meas++;
|
||||
|
||||
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,
|
||||
|
||||
@@ -2061,7 +2061,11 @@ static int pf_ul(gNB_MAC_INST *nrmac,
|
||||
const int max_mcs = min(bo->max_mcs, max_mcs_table); /* no per-user maximum MCS yet */
|
||||
int selected_mcs;
|
||||
if (bo->harq_round_max == 1) {
|
||||
selected_mcs = sched_ctrl->ul_bler_stats.mcs = max_mcs;
|
||||
int nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format);
|
||||
selected_mcs = get_mcs_from_SINRx10(current_BWP->mcs_table, sched_ctrl->pusch_snrx10, nrOfLayers);
|
||||
selected_mcs = min(max_mcs, selected_mcs);
|
||||
selected_mcs = max(bo->min_mcs, selected_mcs);
|
||||
sched_ctrl->ul_bler_stats.mcs = selected_mcs;
|
||||
} else {
|
||||
selected_mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->ul_bler_stats, max_mcs, frame);
|
||||
LOG_D(NR_MAC, "%d.%d starting mcs %d bler %f\n", frame, slot, selected_mcs, sched_ctrl->ul_bler_stats.bler);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -126,24 +126,37 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_mac_stats_t *stats = &UE->mac_stats;
|
||||
const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0;
|
||||
const int avg_sinrx10 = stats->num_sinr_meas > 0 ? stats->cumul_sinrx10 / stats->num_sinr_meas : 0;
|
||||
|
||||
output += snprintf(output, end - output, "UE RNTI %04x CU-UE-ID ", UE->rnti);
|
||||
if (du_exists_f1_ue_data(UE->rnti)) {
|
||||
f1_ue_data_t ued = du_get_f1_ue_data(UE->rnti);
|
||||
output += snprintf(output, end - output, "%d", ued.secondary_ue);
|
||||
} else {
|
||||
output += snprintf(output, end-output, "(none)");
|
||||
output += snprintf(output, end - output, "(none)");
|
||||
}
|
||||
|
||||
bool in_sync = !sched_ctrl->ul_failure;
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
" %s PH %d dB PCMAX %d dBm, average RSRP %d (%d meas)\n",
|
||||
" %s PH %d dB PCMAX %d dBm",
|
||||
in_sync ? "in-sync" : "out-of-sync",
|
||||
sched_ctrl->ph,
|
||||
sched_ctrl->pcmax,
|
||||
avg_rsrp,
|
||||
stats->num_rsrp_meas);
|
||||
sched_ctrl->pcmax);
|
||||
|
||||
if (stats->num_rsrp_meas)
|
||||
output += snprintf(output, end - output, ", average RSRP %d (%d meas)", avg_rsrp, stats->num_rsrp_meas);
|
||||
|
||||
if (stats->num_sinr_meas) {
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
", average SINR %d.%d (%d meas)",
|
||||
avg_sinrx10 / 10,
|
||||
avg_sinrx10 % 10,
|
||||
stats->num_sinr_meas);
|
||||
}
|
||||
|
||||
output += snprintf(output, end - output, "\n");
|
||||
|
||||
if(sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report)
|
||||
output += snprintf(output,
|
||||
@@ -178,6 +191,8 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
||||
if (reset_rsrp) {
|
||||
stats->num_rsrp_meas = 0;
|
||||
stats->cumul_rsrp = 0;
|
||||
stats->num_sinr_meas = 0;
|
||||
stats->cumul_sinrx10 = 0;
|
||||
}
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
|
||||
@@ -521,8 +521,7 @@ typedef struct RSRP_report {
|
||||
uint8_t nr_reports;
|
||||
uint8_t resource_id[MAX_NR_OF_REPORTED_RS];
|
||||
int RSRP[MAX_NR_OF_REPORTED_RS];
|
||||
// SINR index according to tables 10.1.16.1-1, 10.1.16.1-2
|
||||
int SINR_index[MAX_NR_OF_REPORTED_RS];
|
||||
int SINRx10[MAX_NR_OF_REPORTED_RS];
|
||||
} RSRP_report_t;
|
||||
|
||||
struct CSI_Report {
|
||||
@@ -694,6 +693,8 @@ typedef struct NR_mac_stats {
|
||||
uint32_t pucch0_DTX;
|
||||
int cumul_rsrp;
|
||||
uint8_t num_rsrp_meas;
|
||||
int cumul_sinrx10;
|
||||
uint8_t num_sinr_meas;
|
||||
char srs_stats[50]; // Statistics may differ depending on SRS usage
|
||||
int pusch_snrx10;
|
||||
int deltaMCS;
|
||||
|
||||
Reference in New Issue
Block a user