From 924f28ed70492919ee7a3fc1df4c4eb3a0917879 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 21 Aug 2025 19:21:33 +0200 Subject: [PATCH] Refactor to call post-processor in place Call the post-processor when the allocation is "fixed" (i.e., nothing changes anymore), instead of having a final loop across all UEs that might potentially be costly. In order to calculate the PF metric, note that the statistics "reset" is moved into pf_dl() instead of the post-processing loop, as it has to be done on each slot. See also: dd9803020227 ("Refactor to call post-processor in place") --- openair1/SIMULATION/NR_PHY/dlsim.c | 35 +++++---- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 73 ++++++++----------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 8 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 3 - openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 3 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 4 +- 6 files changed, 58 insertions(+), 68 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 3a4df8d2fc..9b3d4ac21b 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -182,13 +182,13 @@ extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration /* specific dlsim DL preprocessor: uses rbStart/rbSize/mcs/nrOfLayers from command line of dlsim */ int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1, g_nrOfLayers = 1, g_pmi = 0; -void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) +void nr_dlsim_preprocessor(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pp_pdsch) { - NR_UE_info_t *UE_info = RC.nrmac[module_id]->UE_info.connected_ue_list[0]; - AssertFatal(RC.nrmac[module_id]->UE_info.connected_ue_list[1] == NULL, "Only single UE allowed in dlsim\n"); + NR_UE_info_t *UE_info = nr_mac->UE_info.connected_ue_list[0]; + AssertFatal(nr_mac->UE_info.connected_ue_list[1] == NULL, "Only single UE allowed in dlsim\n"); NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl; NR_UE_DL_BWP_t *current_BWP = &UE_info->current_DL_BWP; - NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon; + NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon; uint8_t nr_of_candidates = 0; if (g_mcsIndex < 4) { @@ -201,8 +201,8 @@ void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) &nr_of_candidates, sched_ctrl->search_space,4); } - uint32_t Y = get_Y(sched_ctrl->search_space, slot, UE_info->rnti); - int CCEIndex = find_pdcch_candidate(RC.nrmac[module_id], + uint32_t Y = get_Y(sched_ctrl->search_space, pp_pdsch->slot, UE_info->rnti); + int CCEIndex = find_pdcch_candidate(nr_mac, /* CC_id = */ 0, sched_ctrl->aggregation_level, nr_of_candidates, @@ -210,13 +210,18 @@ void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) &sched_ctrl->sched_pdcch, sched_ctrl->coreset, Y); - AssertFatal(CCEIndex>=0, "%4d.%2d could not find CCE for DL DCI UE %d/RNTI %04x\n", frame, slot, 0, UE_info->rnti); + AssertFatal(CCEIndex >= 0, + "%4d.%2d could not find CCE for DL DCI UE %d/RNTI %04x\n", + pp_pdsch->frame, + pp_pdsch->slot, + 0, + UE_info->rnti); sched_ctrl->cce_index = CCEIndex; NR_sched_pdsch_t sched_pdsch = { .rbStart = g_rbStart, .rbSize = g_rbSize, - .bwp_info = get_pdsch_bwp_start_size(RC.nrmac[module_id], UE_info), + .bwp_info = get_pdsch_bwp_start_size(nr_mac, UE_info), .mcs = g_mcsIndex, .nrOfLayers = g_nrOfLayers, .pm_index = g_pmi, @@ -224,7 +229,7 @@ void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) /* the following might override the table that is mandated by RRC * configuration */ current_BWP->mcsTableIdx = g_mcsTableIdx; - sched_pdsch.time_domain_allocation = get_dl_tda(RC.nrmac[module_id], slot); + sched_pdsch.time_domain_allocation = get_dl_tda(nr_mac, pp_pdsch->slot); AssertFatal(sched_pdsch.time_domain_allocation >= 0,"Unable to find PDSCH time domain allocation in list\n"); sched_pdsch.tda_info = get_dl_tda_info(current_BWP, @@ -253,7 +258,7 @@ void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) sched_pdsch.nrOfLayers) >> 3; /* the simulator assumes the HARQ PID is equal to the slot number */ - sched_pdsch.dl_harq_pid = slot; + sched_pdsch.dl_harq_pid = pp_pdsch->slot; /* The scheduler uses lists to track whether a HARQ process is * free/busy/awaiting retransmission, and updates the HARQ process states. @@ -262,17 +267,17 @@ void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) * Therefore, below lines just "repair" everything so that the scheduler * won't remark that there is no HARQ feedback */ sched_ctrl->feedback_dl_harq.head = -1; // always overwrite feedback HARQ process - if (sched_ctrl->harq_processes[slot].round == 0) // depending on round set in simulation ... - add_front_nr_list(&sched_ctrl->available_dl_harq, slot); // ... make PID available + if (sched_ctrl->harq_processes[pp_pdsch->slot].round == 0) // depending on round set in simulation ... + add_front_nr_list(&sched_ctrl->available_dl_harq, pp_pdsch->slot); // ... make PID available else - add_front_nr_list(&sched_ctrl->retrans_dl_harq, slot); // ... make PID retransmission - sched_ctrl->harq_processes[slot].is_waiting = false; + add_front_nr_list(&sched_ctrl->retrans_dl_harq, pp_pdsch->slot); // ... make PID retransmission + sched_ctrl->harq_processes[pp_pdsch->slot].is_waiting = false; AssertFatal(sched_pdsch.rbStart >= 0, "invalid rbStart %d\n", sched_pdsch.rbStart); AssertFatal(sched_pdsch.rbSize > 0, "invalid rbSize %d\n", sched_pdsch.rbSize); AssertFatal(sched_pdsch.mcs >= 0, "invalid mcs %d\n", sched_pdsch.mcs); AssertFatal(current_BWP->mcsTableIdx >= 0 && current_BWP->mcsTableIdx <= 2, "invalid mcsTableIdx %d\n", current_BWP->mcsTableIdx); - sched_ctrl->sched_pdsch = sched_pdsch; + post_process_dlsch(nr_mac, pp_pdsch, UE_info, &sched_pdsch); } nrUE_params_t nrUE_params; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 4a39969be4..aa184d8f85 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -422,17 +422,17 @@ bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) return bwp_info; } -static bool allocate_dl_retransmission(module_id_t module_id, - frame_t frame, - slot_t slot, +static bool allocate_dl_retransmission(gNB_MAC_INST *nr_mac, + post_process_pdsch_t *pp_pdsch, int *n_rb_sched, NR_UE_info_t *UE, int beam_idx, int current_harq_pid) { - + frame_t frame = pp_pdsch->frame; + slot_t slot = pp_pdsch->slot; int CC_id = 0; - gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + const NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels->ServingCellConfigCommon; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; @@ -578,7 +578,8 @@ static bool allocate_dl_retransmission(module_id_t module_id, new_sched.rbStart = rbStart - bwp_info.bwpStart; new_sched.pucch_allocation = alloc; new_sched.bwp_info = bwp_info; - sched_ctrl->sched_pdsch = new_sched; + + post_process_dlsch(nr_mac, pp_pdsch, UE, &new_sched); /* retransmissions: directly allocate */ *n_rb_sched -= new_sched.rbSize; @@ -606,15 +607,16 @@ static int comparator(const void *p, const void *q) return 0; } -static void pf_dl(module_id_t module_id, - frame_t frame, - slot_t slot, +static void pf_dl(gNB_MAC_INST *mac, + post_process_pdsch_t *pp_pdsch, NR_UE_info_t **UE_list, int max_num_ue, int num_beams, int n_rb_sched[num_beams]) { - gNB_MAC_INST *mac = RC.nrmac[module_id]; + frame_t frame = pp_pdsch->frame; + slot_t slot = pp_pdsch->slot; + NR_ServingCellConfigCommon_t *scc=mac->common_channels[0].ServingCellConfigCommon; // UEs that could be scheduled UEsched_t UE_sched[MAX_MOBILES_PER_GNB + 1] = {0}; @@ -633,15 +635,18 @@ static void pf_dl(module_id_t module_id, if (!nr_mac_ue_is_active(UE)) continue; - const NR_mac_dir_stats_t *stats = &UE->mac_stats.dl; + NR_mac_dir_stats_t *stats = &UE->mac_stats.dl; /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ int harq_pid = sched_ctrl->retrans_dl_harq.head; /* Calculate Throughput */ const float a = 0.01f; - const uint32_t b = UE->mac_stats.dl.current_bytes; + const uint32_t b = stats->current_bytes; UE->dl_thr_ue = (1 - a) * UE->dl_thr_ue + a * b; + stats->current_bytes = 0; + stats->current_rbs = 0; + /* Check if this UE should get TA (every 100 frames). If we add the CE, * ta_apply will be reset */ if (frame == ((sched_ctrl->ta_frame + 100) % 1024)) @@ -659,7 +664,7 @@ static void pf_dl(module_id_t module_id, bool sch_ret = beam.idx >= 0; /* Allocate retransmission */ if (sch_ret) - sch_ret = allocate_dl_retransmission(module_id, frame, slot, &n_rb_sched[beam.idx], UE, beam.idx, harq_pid); + sch_ret = allocate_dl_retransmission(mac, pp_pdsch, &n_rb_sched[beam.idx], UE, beam.idx, harq_pid); if (!sch_ret) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] DL retransmission could not be allocated\n", UE->rnti, frame, slot); reset_beam_status(&mac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame, beam.new_beam); @@ -876,7 +881,7 @@ static void pf_dl(module_id_t module_id, &sched_pdsch.tb_size, &sched_pdsch.rbSize); - sched_ctrl->sched_pdsch = sched_pdsch; + post_process_dlsch(mac, pp_pdsch, iterator->UE, &sched_pdsch); /* transmissions: directly allocate */ n_rb_sched[beam.idx] -= sched_pdsch.rbSize; @@ -889,9 +894,9 @@ static void pf_dl(module_id_t module_id, } } -static void nr_dlsch_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) +static void nr_dlsch_preprocessor(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch) { - gNB_MAC_INST *mac = RC.nrmac[module_id]; + module_id_t module_id = 0; NR_UEs_t *UE_info = &mac->UE_info; if (UE_info->connected_ue_list[0] == NULL) @@ -905,7 +910,7 @@ static void nr_dlsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s n_rb_sched[i] = bw; /* Retrieve amount of data to send for this UE */ - nr_store_dlsch_buffer(module_id, frame, slot); + nr_store_dlsch_buffer(module_id, pp_pdsch->frame, pp_pdsch->slot); int average_agg_level = 4; // TODO find a better estimation int max_sched_ues = bw / (average_agg_level * NR_NB_REG_PER_CCE); @@ -914,7 +919,7 @@ static void nr_dlsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET); /* proportional fair scheduling algorithm */ - pf_dl(module_id, frame, slot, UE_info->connected_ue_list, max_sched_ues, num_beams, n_rb_sched); + pf_dl(mac, pp_pdsch, UE_info->connected_ue_list, max_sched_ues, num_beams, n_rb_sched); } nr_pp_impl_dl nr_init_dlsch_preprocessor(int CC_id) @@ -1003,7 +1008,7 @@ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE_info_t *UE, NR_sched_pdsch_t *sched_pdsch) { int CC_id = 0; - int module_id = 0; + int module_id = nr_mac->Mod_id; frame_t frame = pdsch->frame; slot_t slot = pdsch->slot; @@ -1371,6 +1376,8 @@ void nr_schedule_ue_spec(module_id_t module_id, nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; + int CC_id = 0; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ AssertFatal(pthread_mutex_trylock(&gNB_mac->sched_lock) == EBUSY, "this function should be called with the scheduler mutex locked\n"); @@ -1378,34 +1385,14 @@ void nr_schedule_ue_spec(module_id_t module_id, if (!is_dl_slot(slot, &gNB_mac->frame_structure)) return; - /* PREPROCESSOR */ - gNB_mac->pre_processor_dl(module_id, frame, slot); - const int CC_id = 0; NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon; - NR_UEs_t *UE_info = &gNB_mac->UE_info; - nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; - - post_process_pdsch_t pdsch = { frame, slot, dl_req, TX_req }; - const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; gNB_mac->mac_stats.total_prb_aggregate += NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE); - UE_iterator(UE_info->connected_ue_list, UE) { - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; + post_process_pdsch_t pdsch = { frame, slot, dl_req, TX_req }; - if (!nr_mac_ue_is_active(UE) && !get_softmodem_params()->phy_test) - continue; + /* PREPROCESSOR */ + gNB_mac->pre_processor_dl(gNB_mac, &pdsch); - NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; - UE->mac_stats.dl.current_bytes = 0; - UE->mac_stats.dl.current_rbs = 0; - - if (sched_pdsch->rbSize <= 0) - continue; - - post_process_dlsch(gNB_mac, &pdsch, UE, sched_pdsch); - - /* mark UE as scheduled */ - sched_pdsch->rbSize = 0; - } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 10b38272e8..f9121b3125 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -55,9 +55,11 @@ uint32_t target_dl_bw = 50; uint64_t dlsch_slot_bitmap = (1<<1); /* schedules whole bandwidth for first user, all the time */ -void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot) +void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch) { - gNB_MAC_INST *mac = RC.nrmac[module_id]; + frame_t frame = pp_pdsch->frame; + slot_t slot = pp_pdsch->slot; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ int slot_period = slot % mac->frame_structure.numb_slots_period; if (!is_xlsch_in_slot(dlsch_slot_bitmap, slot_period)) @@ -188,7 +190,7 @@ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot) target_dl_Nl) >> 3; - sched_ctrl->sched_pdsch = sched_pdsch; + post_process_dlsch(mac, pp_pdsch, UE, &sched_pdsch); /* mark the corresponding RBs as used */ for (int rb = 0; rb < sched_pdsch.rbSize; rb++) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index d5cda66b5b..a81841d9c0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2974,9 +2974,6 @@ NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroup NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; sched_ctrl->ta_update = 31; - /* set illegal time domain allocation to force recomputation of all fields */ - sched_ctrl->sched_pdsch.time_domain_allocation = -1; - /* Set default BWPs */ AssertFatal(UE->sc_info.n_ul_bwp <= NR_MAX_NUM_BWP, "uplinkBWP_ToAddModList has %d BWP!\n", UE->sc_info.n_ul_bwp); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index f04b28b8da..cfe02755b2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -145,7 +145,7 @@ uint16_t nr_mac_compute_RIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs); /* \brief preprocessor for phytest: schedules UE_id 0 with fixed MCS on all * freq resources */ -void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot); +void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch); /* \brief UL preprocessor for phytest: schedules UE_id 0 with fixed MCS on a * fixed set of resources */ void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch); @@ -504,5 +504,6 @@ void prepare_du_configuration_update(gNB_MAC_INST *mac, void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group); +void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE_info_t *UE, NR_sched_pdsch_t *sched_pdsch); void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE_info_t *UE, NR_sched_pusch_t *sched_pusch); #endif /*__LAYER2_NR_MAC_PROTO_H__*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 544e218e5b..035ab6ad83 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -633,8 +633,6 @@ typedef struct { /// PHR info: nominal UE transmit power levels (dBm) int pcmax; - /// Sched PDSCH: scheduling decisions, copied into HARQ and cleared every TTI - NR_sched_pdsch_t sched_pdsch; /// UE-estimated maximum MCS (from CSI-RS) uint8_t dl_max_mcs; @@ -847,7 +845,7 @@ typedef struct { struct gNB_MAC_INST_s; typedef struct gNB_MAC_INST_s gNB_MAC_INST; -typedef void (*nr_pp_impl_dl)(module_id_t mod_id, frame_t frame, slot_t slot); +typedef void (*nr_pp_impl_dl)(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pp_pdsch); typedef void (*nr_pp_impl_ul)(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch); typedef struct f1_config_t {