From 65e3c89bb1f7abb090a8d716bf0feb890cf69cae Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 27 Sep 2024 13:59:42 +0200 Subject: [PATCH] add ue mac stats and monitoring as per gnb ones --- common/utils/nr/nr_common.h | 1 + executables/nr-ue.c | 20 +++++-- openair1/PHY/INIT/nr_init_ue.c | 8 +-- .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 1 - .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 7 --- openair1/PHY/defs_nr_UE.h | 2 - openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 16 ------ .../NR_UE_PHY/unit_tests/src/pucch_uci_test.c | 22 ++++---- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 3 +- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 36 +++++++++++-- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 3 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 33 ++++++++---- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 47 ++++++++++------ openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 53 ++++++++++++++++++- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h | 2 + 16 files changed, 176 insertions(+), 80 deletions(-) diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 94102a858f..1408f271b0 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -43,6 +43,7 @@ #define MAX_BWP_SIZE 275 #define NR_MAX_NUM_BWP 4 #define NR_MAX_HARQ_PROCESSES 32 +#define NR_MAX_HARQ_ROUNDS_FOR_STATS 16 #define NR_NB_REG_PER_CCE 6 #define NR_NB_SC_PER_RB 12 #define NR_MAX_NUM_LCID 32 diff --git a/executables/nr-ue.c b/executables/nr-ue.c index d6c3086317..a7661b0c06 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -594,7 +594,11 @@ void processSlotTX(void *arg) RU_write(rxtxD, sl_tx_action); } -static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc, int *tx_wait_for_dlsch, nr_phy_data_t *phy_data) +static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, + const UE_nr_rxtx_proc_t *proc, + int *tx_wait_for_dlsch, + nr_phy_data_t *phy_data, + bool *stats_printed) { int sampleShift = INT_MAX; NR_DL_FRAME_PARMS *fp = &UE->frame_parms; @@ -602,7 +606,6 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params; if (IS_SOFTMODEM_NOS1 || IS_SA_MODE(get_softmodem_params())) { - // Start synchronization with a target gNB if (UE->synch_request.received_synch_request == 1) { fapi_nr_synch_request_t *synch_req = &UE->synch_request.synch_req; @@ -655,6 +658,16 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc const int ack_nack_slot = (proc->nr_slot_rx + phy_data->dlsch[0].dlsch_config.k1_feedback) % UE->frame_parms.slots_per_frame; tx_wait_for_dlsch[ack_nack_slot]++; } + } else { + // good time to print statistics, we don't have to spend time to decode DCI + if (proc->frame_rx % 128 == 0) { + if (*stats_printed == false) { + print_ue_mac_stats(UE->Mod_id, proc->frame_rx, proc->nr_slot_rx); + *stats_printed = true; + } + } else { + *stats_printed = false; + } } if (UE->sl_mode == 2) { @@ -833,6 +846,7 @@ void *UE_thread(void *arg) int shiftForNextFrame = 0; int intialSyncOffset = 0; openair0_timestamp sync_timestamp; + bool stats_printed = false; if (get_softmodem_params()->sync_ref && UE->sl_mode == 2) { UE->is_synchronized = 1; @@ -1029,7 +1043,7 @@ void *UE_thread(void *arg) notifiedFIFO_elt_t *newRx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_rx, NULL, UE_dl_processing); nr_rxtx_thread_data_t *curMsgRx = (nr_rxtx_thread_data_t *)NotifiedFifoData(newRx); *curMsgRx = (nr_rxtx_thread_data_t){.proc = curMsg.proc, .UE = UE}; - int ret = UE_dl_preprocessing(UE, &curMsgRx->proc, tx_wait_for_dlsch, &curMsgRx->phy_data); + int ret = UE_dl_preprocessing(UE, &curMsgRx->proc, tx_wait_for_dlsch, &curMsgRx->phy_data, &stats_printed); if (ret != INT_MAX) shiftForNextFrame = ret; pushTpool(&(get_nrUE_params()->Tpool), newRx); diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index a240f3ecde..677401ae47 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -467,10 +467,10 @@ void nr_init_ul_harq_processes(NR_UL_UE_HARQ_t harq_list[NR_MAX_ULSCH_HARQ_PROCE void init_nr_ue_transport(PHY_VARS_NR_UE *ue) { nr_init_dl_harq_processes(ue->dl_harq_processes, NR_MAX_DLSCH_HARQ_PROCESSES, ue->frame_parms.N_RB_DL); - nr_init_ul_harq_processes(ue->ul_harq_processes, NR_MAX_ULSCH_HARQ_PROCESSES, ue->frame_parms.N_RB_UL, ue->frame_parms.nb_antennas_tx); - - for(int i=0; i<5; i++) - ue->dl_stats[i] = 0; + nr_init_ul_harq_processes(ue->ul_harq_processes, + NR_MAX_ULSCH_HARQ_PROCESSES, + ue->frame_parms.N_RB_UL, + ue->frame_parms.nb_antennas_tx); } void clean_UE_harq(PHY_VARS_NR_UE *UE) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 243e3f9a23..58114dfeb5 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -285,7 +285,6 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, } // HARQ stats - phy_vars_ue->dl_stats[harq_process->DLround]++; LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, dlsch->dlsch_config.rv); uint16_t nb_rb;// = 30; uint8_t dmrs_Type = dlsch->dlsch_config.dmrsConfigType; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 6c26a3e59d..176ed67cf3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -200,13 +200,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, #define modOrder(I_MCS,I_TBS) ((I_MCS-I_TBS)*2+2) // Find modulation order from I_TBS and I_MCS #endif -int dump_ue_stats(PHY_VARS_NR_UE *phy_vars_ue, - const UE_nr_rxtx_proc_t *proc, - char *buffer, - int length, - runmode_t mode, - int input_level_dBm); - /*! \brief This function performs the initial cell search procedure - PSS detection, SSS detection and PBCH detection. At the end, the basic frame parameters are known (Frame configuration - TDD/FDD and cyclic prefix length, diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 12b10e4b96..7178faefd1 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -520,8 +520,6 @@ typedef struct PHY_VARS_NR_UE_s { SLIST_HEAD(ral_thresholds_gen_poll_s, ral_threshold_phy_t) ral_thresholds_gen_polled[RAL_LINK_PARAM_GEN_MAX]; SLIST_HEAD(ral_thresholds_lte_poll_s, ral_threshold_phy_t) ral_thresholds_lte_polled[RAL_LINK_PARAM_LTE_MAX]; #endif - int dl_errors; - _Atomic(int) dl_stats[16]; void* scopeData; // Pointers to hold PDSCH data only for phy simulators void *phy_sim_rxdataF; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 2be6faeb9c..a737b5246e 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1010,22 +1010,6 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_ } // for rsc_id } // for gNB_id - if ((frame_rx%64 == 0) && (nr_slot_rx==0)) { - LOG_I(NR_PHY,"============================================\n"); - // fixed text + 8 HARQs rounds à 10 ("999999999/") + NULL - // if we use 999999999 HARQs, that should be sufficient for at least 138 hours - const size_t harq_output_len = 31 + 10 * 8 + 1; - char output[harq_output_len]; - char *p = output; - const char *end = output + harq_output_len; - p += snprintf(p, end - p, "[UE %d] Harq round stats for Downlink: %d", ue->Mod_id, ue->dl_stats[0]); - for (int round = 1; round < 16 && (round < 3 || ue->dl_stats[round] != 0); ++round) - p += snprintf(p, end - p,"/%d", ue->dl_stats[round]); - LOG_I(NR_PHY,"%s\n", output); - - LOG_I(NR_PHY,"============================================\n"); - } - LOG_D(PHY," ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_IN); diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c index 33cd1b3432..1217f70fba 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c @@ -180,7 +180,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr } /* set a tx slot with no ack */ - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; + NR_UE_DL_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; harq_status->slot_for_feedback_ack = proc->nr_slot_tx; @@ -267,7 +267,7 @@ int test_pucch_common_config_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_ common_pucch_configuration(ue, gNB_id, TST_PUCCH_COMMON_CONFIG_INDEX_OK); /* set a tx slot with no ack */ - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; + NR_UE_DL_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; harq_status->ack = DL_ACK; @@ -557,7 +557,7 @@ int test_pucch_dedicated_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_id, int reset_harq = false; int dl_harq_pid[TST_NB_STEP_SINGLE_TRANSPORT_BLOCK] = {TST_DL_HARQ_PID_FIRST, TST_DL_HARQ_PID_SECOND, TST_DL_HARQ_PID_THIRD, TST_DL_HARQ_PID_FOURTH }; int pucch_resource_indicator[TST_NB_STEP_SINGLE_TRANSPORT_BLOCK][2] = { { 0, 4 }, { 1, 0 } , { 1, 3 } , { 5, 7 } }; - NR_UE_HARQ_STATUS_t *harq_status; + NR_UE_DL_HARQ_STATUS_t *harq_status; ue->PDSCH_Config.maxNrofCodeWordsScheduledByDCI = nb_code_n1; @@ -584,7 +584,7 @@ int test_pucch_dedicated_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_id, /* set a tx slot with no ack */ ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid = dl_harq_pid[i]; - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; + NR_UE_DL_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; @@ -618,7 +618,7 @@ int test_pucch_dedicated_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_id, /* set a tx slot with no ack */ ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid = dl_harq_pid[i]; - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; + NR_UE_DL_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; @@ -662,7 +662,7 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE int reset_harq = false; int dl_harq_pid[TST_NB_STEP_TWO_TRANSPORT_BLOCKS] = {TST_DL_HARQ_PID_FIRST, TST_DL_HARQ_PID_SECOND, TST_DL_HARQ_PID_THIRD, TST_DL_HARQ_PID_FOURTH }; int pucch_resource_indicator[TST_NB_STEP_TWO_TRANSPORT_BLOCKS][2] = { { 0, 1 }, { 3, 7 } , { 2 , 4 } , { 4 , 6 } }; - NR_UE_HARQ_STATUS_t *harq_status; + NR_UE_DL_HARQ_STATUS_t *harq_status; int TB_identifier = 1; int thread_number = TST_THREAD_ID; @@ -682,7 +682,7 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE /* set a tx slot with no ack */ ue->dlsch[proc->thread_id][gNB_id][code_word]->current_harq_pid = dl_harq_pid[i]; - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][code_word]->harq_processes[dl_harq_pid[i]].harq_ack; + NR_UE_DL_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][code_word]->harq_processes[dl_harq_pid[i]].harq_ack; harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; @@ -725,7 +725,7 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE /* set a tx slot with no ack */ ue->dlsch[proc->thread_id][gNB_id][code_word]->current_harq_pid = dl_harq_pid[i]; - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][code_word]->harq_processes[dl_harq_pid[i]].harq_ack; + NR_UE_DL_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][code_word]->harq_processes[dl_harq_pid[i]].harq_ack; harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; @@ -759,7 +759,7 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE /* set a tx slot with no ack */ ue->dlsch[proc->thread_id][gNB_id][code_word]->current_harq_pid = dl_harq_pid[i]; - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][code_word]->harq_processes[dl_harq_pid[i]].harq_ack; + NR_UE_DL_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][code_word]->harq_processes[dl_harq_pid[i]].harq_ack; harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; @@ -973,7 +973,7 @@ int test_sr_ack_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pro /* set a first harq ack context */ - NR_UE_HARQ_STATUS_t *harq_status; + NR_UE_DL_HARQ_STATUS_t *harq_status; ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_FIRST; @@ -1085,7 +1085,7 @@ int test_csi_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *proc) /* set a first harq ack context */ - NR_UE_HARQ_STATUS_t *harq_status; + NR_UE_DL_HARQ_STATUS_t *harq_status; ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_FIRST; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 28bf3bfc8e..08cfd7303c 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -2232,8 +2232,7 @@ static const uint16_t Table_51311[32][2] = {{2, 1200}, {2, 1570}, {2, 1930}, {2, {4, 6580}, {6, 4380}, {6, 4660}, {6, 5170}, {6, 5670}, {6, 6160}, {6, 6660}, {6, 7190}, {6, 7720}, {6, 8220}, {6, 8730}, {6, 9100}, {6, 9480}, {2, 0}, {4, 0}, {6, 0}}; -//Table 5.1.3.1-2 of 38.214 -// Imcs values 20 and 26 have been multiplied by 2 to avoid the floating point +// Table 5.1.3.1-2 of 38.214 static const uint16_t Table_51312[32][2] = {{2, 1200}, {2, 1930}, {2, 3080}, {2, 4490}, {2, 6020}, {4, 3780}, {4, 4340}, {4, 4900}, {4, 5530}, {4, 6160}, {4, 6580}, {6, 4660}, {6, 5170}, {6, 5670}, {6, 6160}, {6, 6660}, {6, 7190}, {6, 7720}, {6, 8220}, {6, 8730}, {8, 6825}, diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 1530846d6b..ca60310b45 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -385,13 +385,15 @@ typedef struct { uint32_t R; uint32_t TBS; int last_ndi; -} NR_UE_HARQ_STATUS_t; + int round; +} NR_UE_DL_HARQ_STATUS_t; typedef struct { uint32_t R; uint32_t TBS; int last_ndi; -} NR_UL_HARQ_INFO_t; + int round; +} NR_UE_UL_HARQ_INFO_t; typedef struct { uint8_t freq_hopping; @@ -510,6 +512,31 @@ typedef enum { ON_PUSCH } CSI_mapping_t; +typedef struct { + uint64_t rounds[NR_MAX_HARQ_ROUNDS_FOR_STATS]; + uint64_t total_bits; + uint64_t total_symbols; + uint64_t target_code_rate; + uint64_t qam_mod_order; + uint64_t rb_size; + uint64_t nr_of_symbols; +} ue_mac_dir_stats_t; + +typedef struct { + ue_mac_dir_stats_t dl; + ue_mac_dir_stats_t ul; + uint32_t bad_dci; + uint32_t ulsch_DTX; + uint64_t ulsch_total_bytes_scheduled; + uint32_t pucch0_DTX; + int cumul_rsrp; + uint8_t num_rsrp_meas; + char srs_stats[50]; // Statistics may differ depending on SRS usage + int pusch_snrx10; + int deltaMCS; + int NPRB; +} ue_mac_stats_t; + /*!\brief Top level UE MAC structure */ typedef struct NR_UE_MAC_INST_s { module_id_t ue_id; @@ -594,8 +621,8 @@ typedef struct NR_UE_MAC_INST_s { // Defined for abstracted mode nr_downlink_indication_t dl_info; - NR_UE_HARQ_STATUS_t dl_harq_info[NR_MAX_HARQ_PROCESSES]; - NR_UL_HARQ_INFO_t ul_harq_info[NR_MAX_HARQ_PROCESSES]; + NR_UE_DL_HARQ_STATUS_t dl_harq_info[NR_MAX_HARQ_PROCESSES]; + NR_UE_UL_HARQ_INFO_t ul_harq_info[NR_MAX_HARQ_PROCESSES]; NR_TAG_Id_t tag_Id; A_SEQUENCE_OF(NR_TAG_t) TAG_list; @@ -615,6 +642,7 @@ typedef struct NR_UE_MAC_INST_s { bool pusch_power_control_initialized; int delta_msg2; pthread_mutex_t if_mutex; + ue_mac_stats_t stats; } NR_UE_MAC_INST_t; /*@}*/ diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 68dd57efd1..8ad8d673b8 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -240,8 +240,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) nr_mac->scheduling_info.phr_info.was_mac_reset = true; // flush the soft buffers for all DL HARQ processes - for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) - memset(&nr_mac->dl_harq_info[k], 0, sizeof(NR_UE_HARQ_STATUS_t)); + memset(nr_mac->dl_harq_info, 0, sizeof(nr_mac->dl_harq_info)); // for each DL HARQ process, consider the next received transmission for a TB as the very first transmission for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 53f29ff056..26fcd95757 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -1053,7 +1053,7 @@ void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac) void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) { - NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid]; + NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid]; int sched_slot = current_harq->ul_slot; int sched_frame = current_harq->ul_frame; mac->nr_ue_emul_l1.num_harqs = 1; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index c871a696da..5376d85ef8 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -806,7 +806,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, /* MCS */ dlsch_pdu->mcs = dci->mcs; - NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val]; + NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val]; /* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ if (dl_conf_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH || dl_conf_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH || @@ -815,9 +815,9 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, dlsch_pdu->new_data_indicator = true; current_harq->R = 0; current_harq->TBS = 0; - } - else + } else { dlsch_pdu->new_data_indicator = false; + } if (dl_conf_req->pdu_type != FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH && dl_conf_req->pdu_type != FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH) { @@ -935,6 +935,12 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, dci_ind->N_CCE, frame, slot); + if (dlsch_pdu->new_data_indicator) + current_harq->round = 0; + else + current_harq->round++; + if (current_harq->round < sizeofArray(mac->stats.dl.rounds)) + mac->stats.dl.rounds[current_harq->round]++; } LOG_D(MAC, @@ -1126,7 +1132,7 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, /* MCS (for transport block 1)*/ dlsch_pdu->mcs = dci->mcs; /* NDI (for transport block 1)*/ - NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val]; + NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val]; if (dci->ndi != current_harq->last_ndi) { // new data dlsch_pdu->new_data_indicator = true; @@ -1275,6 +1281,12 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, dci_ind->N_CCE, frame, slot); + if (dlsch_pdu->new_data_indicator) + current_harq->round = 0; + else + current_harq->round++; + if (current_harq->round < sizeofArray(mac->stats.dl.rounds)) + mac->stats.dl.rounds[current_harq->round]++; // send the ack/nack slot number to phy to indicate tx thread to wait for DLSCH decoding dlsch_pdu->k1_feedback = feedback_ti; @@ -1432,10 +1444,11 @@ nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, dci->ss_type, dci->payloadBits, slot); if (format == NR_DCI_NONE) return NR_DCI_NONE; - dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][format]; - int ret = nr_ue_process_dci(mac, frame, slot, def_dci_pdu_rel15, dci, format); - if (ret < 0) + int ret = nr_ue_process_dci(mac, frame, slot, mac->def_dci_pdu_rel15[slot] + format, dci, format); + if (ret < 0) { + mac->stats.bad_dci++; return NR_DCI_NONE; + } return format; } @@ -1459,7 +1472,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac, frame_t frame, int slot) { - NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id]; + NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id]; current_harq->active = true; current_harq->ack_received = false; current_harq->pucch_resource_indicator = pucch_id; @@ -1486,7 +1499,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac, // looking for other active HARQ processes with feedback in the same frame/slot if (i == harq_id) continue; - NR_UE_HARQ_STATUS_t *harq = &mac->dl_harq_info[i]; + NR_UE_DL_HARQ_STATUS_t *harq = &mac->dl_harq_info[i]; if (harq->active && harq->ul_frame == current_harq->ul_frame && harq->ul_slot == current_harq->ul_slot) { @@ -2331,7 +2344,7 @@ bool get_downlink_ack(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sche for (int dl_harq_pid = 0; dl_harq_pid < num_dl_harq; dl_harq_pid++) { - NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dl_harq_pid]; + NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dl_harq_pid]; if (current_harq->active) { LOG_D(PHY, "HARQ pid %d is active for %d.%d\n", diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index ff44c21541..65597bd3dd 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -166,8 +166,8 @@ void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac) { // flush all HARQ buffers for all Serving Cells for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { - memset(&mac->dl_harq_info[k], 0, sizeof(NR_UE_HARQ_STATUS_t)); - memset(&mac->ul_harq_info[k], 0, sizeof(NR_UL_HARQ_INFO_t)); + memset(&mac->dl_harq_info[k], 0, sizeof(*mac->dl_harq_info)); + memset(&mac->ul_harq_info[k], 0, sizeof(*mac->ul_harq_info)); mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value } @@ -704,6 +704,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, 0, f_alloc) < 0) { LOG_E(NR_MAC, "can't nr_ue_process_dci_freq_dom_resource_assignment()\n"); + mac->stats.bad_dci++; return -1; } @@ -713,7 +714,6 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, // Time domain allocation pusch_config_pdu->start_symbol_index = tda_info->startSymbolIndex; pusch_config_pdu->nr_of_symbols = tda_info->nrOfSymbols; - l_prime_mask = get_l_prime(tda_info->nrOfSymbols, tda_info->mapping_type, add_pos, @@ -817,11 +817,13 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, ul_ports_config(mac, &dmrslength, pusch_config_pdu, dci, dci_format); } else { LOG_E(NR_MAC, "UL grant from DCI format %d is not handled...\n", dci_format); + mac->stats.bad_dci++; return -1; } if (pusch_config_pdu->nrOfLayers < 1) { LOG_E(NR_MAC, "Invalid UL number of layers %d from DCI\n", pusch_config_pdu->nrOfLayers); + mac->stats.bad_dci++; return -1; } @@ -892,6 +894,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, 0, dci->frequency_domain_assignment) < 0) { LOG_E(NR_MAC, "can't nr_ue_process_dci_freq_dom_resource_assignment()\n"); + mac->stats.bad_dci++; return -1; } @@ -910,18 +913,20 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->mcs_table = get_pusch_mcs_table(mcs_table_config, tp_enabled, dci_format, rnti_type, ss_type, false); /* NDI */ - NR_UL_HARQ_INFO_t *harq = &mac->ul_harq_info[dci->harq_pid.val]; + const int pid = dci->harq_pid.val; + NR_UE_UL_HARQ_INFO_t *harq = &mac->ul_harq_info[pid]; pusch_config_pdu->pusch_data.new_data_indicator = false; if (dci->ndi != harq->last_ndi) { pusch_config_pdu->pusch_data.new_data_indicator = true; // if new data reset harq structure memset(harq, 0, sizeof(*harq)); - } + } else + harq->round++; harq->last_ndi = dci->ndi; /* RV */ pusch_config_pdu->pusch_data.rv_index = dci->rv; /* HARQ_PROCESS_NUMBER */ - pusch_config_pdu->pusch_data.harq_process_id = dci->harq_pid.val; + pusch_config_pdu->pusch_data.harq_process_id = pid; if (NR_DMRS_ulconfig != NULL) add_pos = (NR_DMRS_ulconfig->dmrs_AdditionalPosition == NULL) ? 2 : *NR_DMRS_ulconfig->dmrs_AdditionalPosition; @@ -994,6 +999,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->qam_mod_order = nr_get_Qm_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); if (pusch_config_pdu->qam_mod_order == 0) { LOG_W(NR_MAC, "Invalid Mod order, likely due to unexpected UL DCI. Ignoring DCI! \n"); + mac->stats.bad_dci++; return -1; } @@ -1001,15 +1007,16 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, int number_of_symbols = pusch_config_pdu->nr_of_symbols; int number_dmrs_symbols = 0; for (int i = start_symbol; i < start_symbol + number_of_symbols; i++) { - if((pusch_config_pdu->ul_dmrs_symb_pos >> i) & 0x01) + if ((pusch_config_pdu->ul_dmrs_symb_pos >> i) & 0x01) number_dmrs_symbols += 1; } - int nb_dmrs_re_per_rb = ((pusch_config_pdu->dmrs_config_type == pusch_dmrs_type1) ? 6 : 4) * pusch_config_pdu->num_dmrs_cdm_grps_no_data; + int nb_dmrs_re_per_rb = + ((pusch_config_pdu->dmrs_config_type == pusch_dmrs_type1) ? 6 : 4) * pusch_config_pdu->num_dmrs_cdm_grps_no_data; // Compute TBS uint16_t R = nr_get_code_rate_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); - int pid = pusch_config_pdu->pusch_data.harq_process_id; + const int pid = pusch_config_pdu->pusch_data.harq_process_id; if (R > 0) { pusch_config_pdu->target_code_rate = R; pusch_config_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_config_pdu->qam_mod_order, @@ -1022,8 +1029,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->nrOfLayers) >> 3; mac->ul_harq_info[pid].TBS = pusch_config_pdu->pusch_data.tb_size; mac->ul_harq_info[pid].R = R; - } - else { + } else { pusch_config_pdu->target_code_rate = mac->ul_harq_info[pid].R; pusch_config_pdu->pusch_data.tb_size = mac->ul_harq_info[pid].TBS; } @@ -1052,7 +1058,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->rb_start, pusch_config_pdu->nr_of_symbols, nb_dmrs_re_per_rb * number_dmrs_symbols, - 0, //TODO: count PTRS per RB + 0, // TODO: count PTRS per RB pusch_config_pdu->qam_mod_order, pusch_config_pdu->target_code_rate, pusch_config_pdu->pusch_uci.beta_offset_csi1, @@ -1063,12 +1069,13 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->ldpcBaseGraph = get_BG(pusch_config_pdu->pusch_data.tb_size << 3, pusch_config_pdu->target_code_rate); - //The MAC entity shall restart retxBSR-Timer upon reception of a grant for transmission of new data on any UL-SCH + // The MAC entity shall restart retxBSR-Timer upon reception of a grant for transmission of new data on any UL-SCH if (pusch_config_pdu->pusch_data.new_data_indicator && dci && dci->ulsch_indicator) nr_timer_start(&mac->scheduling_info.retxBSR_Timer); if (pusch_config_pdu->pusch_data.tb_size == 0) { LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n"); + mac->stats.bad_dci++; return -1; } @@ -1081,6 +1088,14 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, nr_timer_start(&mac->scheduling_info.phr_info.periodicPHR_Timer); } } + if (mac->ul_harq_info[pid].round < sizeofArray(mac->stats.ul.rounds)) + mac->stats.ul.rounds[mac->ul_harq_info[pid].round]++; + int bits = pusch_config_pdu->pusch_data.tb_size; + mac->stats.ul.total_bits += bits; + mac->stats.ul.target_code_rate += pusch_config_pdu->target_code_rate * bits; + mac->stats.ul.total_symbols += bits / pusch_config_pdu->qam_mod_order; + mac->stats.ul.rb_size += pusch_config_pdu->rb_size; + mac->stats.ul.nr_of_symbols += pusch_config_pdu->nr_of_symbols; return 0; } @@ -2124,9 +2139,9 @@ static void map_ssb_to_ro(NR_UE_MAC_INST_t *mac) tx_ssb->nb_mapped_ro); // If all the required SSBs are mapped to this RO, exit the loop of SSBs if (ro_p->nb_mapped_ssb == ssb_rach_ratio) { - idx++; - break; - } + idx++; + break; + } } done = MAX_NB_SSB == idx; } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 10faa6cc65..44118704a4 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -67,6 +67,57 @@ queue_t nr_ul_dci_req_queue; queue_t nr_ul_tti_req_queue; static void save_pdsch_pdu_for_crnti(nfapi_nr_dl_tti_request_t *dl_tti_request); +void print_ue_mac_stats(const module_id_t mod, const int frame_rx, const int slot_rx) +{ + NR_UE_MAC_INST_t *mac = get_mac_inst(mod); + int ret = pthread_mutex_lock(&mac->if_mutex); + AssertFatal(!ret, "mutex failed %d\n", ret); + + char txt[1024]; + char *end = txt + sizeof(txt); + char *cur = txt; + + float nbul = 0; + for (uint64_t *p = mac->stats.ul.rounds; p < mac->stats.ul.rounds + NR_MAX_HARQ_ROUNDS_FOR_STATS; p++) + nbul += *p; + if (nbul < 1) + nbul = 1; + + float nbdl = 0; + for (uint64_t *p = mac->stats.dl.rounds; p < mac->stats.dl.rounds + NR_MAX_HARQ_ROUNDS_FOR_STATS; p++) + nbdl += *p; + if (nbdl < 1) + nbdl = 1; + + cur += snprintf(cur, end - cur, "UE %d stats sfn: %d.%d, cumulated bad DCI %d\n", mod, frame_rx, slot_rx, mac->stats.bad_dci); + + cur += snprintf(cur, end - cur, " DL harq: %lu", mac->stats.dl.rounds[0]); + int nb; + for (nb = NR_MAX_HARQ_ROUNDS_FOR_STATS - 1; nb > 1; nb--) + if (mac->stats.ul.rounds[nb]) + break; + for (int i = 1; i < nb + 1; i++) + cur += snprintf(cur, end - cur, "/%lu", mac->stats.dl.rounds[i]); + + cur += snprintf(cur, end - cur, "\n Ul harq: %lu", mac->stats.ul.rounds[0]); + for (nb = NR_MAX_HARQ_ROUNDS_FOR_STATS - 1; nb > 1; nb--) + if (mac->stats.ul.rounds[nb]) + break; + for (int i = 1; i < nb + 1; i++) + cur += snprintf(cur, end - cur, "/%lu", mac->stats.ul.rounds[i]); + snprintf(cur, + end - cur, + " avg code rate %.01f, avg bit/symbol %.01f, avg per TB: " + "(nb RBs %.01f, nb symbols %.01f)\n", + (double)mac->stats.ul.target_code_rate / (mac->stats.ul.total_bits * 1024 * 10), // See const Table_51311 definition + (double)mac->stats.ul.total_bits / mac->stats.ul.total_symbols, + mac->stats.ul.rb_size / nbul, + mac->stats.ul.nr_of_symbols / nbul); + LOG_I(NR_MAC, "%s", txt); + ret = pthread_mutex_unlock(&mac->if_mutex); + AssertFatal(!ret, "mutex failed %d\n", ret); +} + void nrue_init_standalone_socket(int tx_port, int rx_port) { { @@ -1120,7 +1171,7 @@ static int8_t handle_csirs_measurements(NR_UE_MAC_INST_t *mac, void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nack) { - NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid]; + NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid]; if (current_harq->active) { LOG_D(PHY,"Updating harq_status for harq_id %d, ack/nak %d\n", harq_pid, current_harq->ack); diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h index 6654fc8bff..c43eef87a3 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h @@ -322,5 +322,7 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info); void nr_ue_sl_indication(nr_sidelink_indication_t *sl_indication); +void print_ue_mac_stats(const module_id_t mod, const int frame_rx, const int slot_rx); + #endif