From 733c7e5e8949c33b174bdf7ce98ec5ca8594faa1 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Sun, 19 Feb 2023 17:42:52 +0100 Subject: [PATCH] bugfix: change memory management of interface between PHY and MAC scheduler This commit fixes a bug caused by global variables in the gNB_MAC_INST structure used to transfer MAC scheduler's results to the PHY layer. When using several threads in the PHY layer, it may happen that the MAC scheduler is called a second time by the second PHY thread for the next slot before the content of the global variables in the gNB_MAC_INST structure used to store the result of the MAC scheduler for the current slot have been consumed by the first thread, leading to unpredictable results (all of them certainly wrong). The solution is to introduce a small memory management module for the interface between the PHY threads and the MAC scheduler. The MAC scheduler now fills the data structures passed to it, and not a global variable anymore. The PHY layer manages the structures and ensures that no data is overwritten before being fully consumed by the various threads of the PHY layer. Some care has to be taken because several PHY threads will access the same structures at the same time for a given slot (in read mode, so it's okay). A mechanism of reference counting has thus been introduced. Only one CC is supported. This restriction should not be too hard to remove if/when needed. (The code before this commit does not seem to work for more than one CC anyway.) --- CMakeLists.txt | 1 + executables/nr-gnb.c | 3 + openair1/PHY/defs_gNB.h | 2 + openair1/SCHED_NR/fapi_nr_l1.c | 20 ++- openair1/SIMULATION/NR_PHY/dlschsim.c | 11 ++ openair1/SIMULATION/NR_PHY/dlsim.c | 33 ++-- openair1/SIMULATION/NR_PHY/pbchsim.c | 11 ++ openair1/SIMULATION/NR_PHY/prachsim.c | 11 ++ openair1/SIMULATION/NR_PHY/pucchsim.c | 11 ++ openair1/SIMULATION/NR_PHY/ulschsim.c | 11 ++ openair1/SIMULATION/NR_PHY/ulsim.c | 4 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 81 +++++++--- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 85 ++++++---- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 28 ++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 18 ++- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 9 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 4 +- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 69 +++++--- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 9 -- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 30 ++-- openair2/NR_PHY_INTERFACE/NR_IF_Module.h | 10 +- openair2/NR_PHY_INTERFACE/nr_sched_response.c | 153 ++++++++++++++++++ openair2/NR_PHY_INTERFACE/nr_sched_response.h | 32 ++++ 23 files changed, 497 insertions(+), 149 deletions(-) create mode 100644 openair2/NR_PHY_INTERFACE/nr_sched_response.c create mode 100644 openair2/NR_PHY_INTERFACE/nr_sched_response.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 691cb4aaa8..04f87ad8ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1474,6 +1474,7 @@ set (MAC_SRC set (MAC_NR_SRC ${NR_PHY_INTERFACE_DIR}/NR_IF_Module.c + ${NR_PHY_INTERFACE_DIR}/nr_sched_response.c ${NR_GNB_MAC_DIR}/main.c ${NR_GNB_MAC_DIR}/config.c ${NR_GNB_MAC_DIR}/gNB_scheduler.c diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 05516e01b4..773f89416c 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -51,6 +51,7 @@ #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/MODULATION/nr_modulation.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" +#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" #undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all @@ -126,6 +127,8 @@ void tx_func(void *param) { 1); clock_gettime(CLOCK_MONOTONIC,&info->gNB->rt_L1_profiling.return_L1_TX[rt_prof_idx]); + /* this thread is done with the sched_info, decrease the reference counter */ + deref_sched_response(info->sched_response_id); } void rx_func(void *param) diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 1c248bc4a9..71853765af 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -823,6 +823,8 @@ typedef struct processingData_L1tx { uint16_t num_pdsch_slot; int num_dl_pdcch; int num_ul_pdcch; + /* a reference to the sched_response, to release it when not needed anymore */ + int sched_response_id; } processingData_L1tx_t; #endif diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 43223906d5..6f644c4ba5 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -35,6 +35,7 @@ #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "PHY/NR_TRANSPORT/nr_dci.h" #include "nfapi/oai_integration/vendor_ext.h" +#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" extern int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); extern int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req); @@ -131,10 +132,10 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO) { // copy data from L2 interface into L1 structures module_id_t Mod_id = Sched_INFO->module_id; - nfapi_nr_dl_tti_request_t *DL_req = Sched_INFO->DL_req; - nfapi_nr_tx_data_request_t *TX_req = Sched_INFO->TX_req; - nfapi_nr_ul_tti_request_t *UL_tti_req = Sched_INFO->UL_tti_req; - nfapi_nr_ul_dci_request_t *UL_dci_req = Sched_INFO->UL_dci_req; + nfapi_nr_dl_tti_request_t *DL_req = &Sched_INFO->DL_req; + nfapi_nr_tx_data_request_t *TX_req = &Sched_INFO->TX_req; + nfapi_nr_ul_tti_request_t *UL_tti_req = &Sched_INFO->UL_tti_req; + nfapi_nr_ul_dci_request_t *UL_dci_req = &Sched_INFO->UL_dci_req; frame_t frame = Sched_INFO->frame; sub_frame_t slot = Sched_INFO->slot; @@ -169,6 +170,8 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO) msgTx->num_ul_pdcch = number_ul_dci_pdu; msgTx->slot = slot; msgTx->frame = frame; + /* store the sched_response_id for the TX thread to release it when done */ + msgTx->sched_response_id = Sched_INFO->sched_response_id; for (int i=0;idl_tti_request_body.dl_tti_pdu_list[i]; @@ -208,6 +211,11 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO) for (int i=0; iul_pdcch_pdu[i] = UL_dci_req->ul_dci_pdu_list[i]; + /* Both the current thread and the TX thread will access the sched_info + * at the same time, so increase its reference counter, so that it is + * released only when both threads are done with it. + */ + inc_ref_sched_response(Sched_INFO->sched_response_id); pushNotifiedFIFO(&gNB->L1_tx_filled,res); } @@ -250,5 +258,9 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO) if (number_dl_pdu>0) oai_nfapi_dl_tti_req(DL_req); } + + /* this thread is done with the sched_info, decrease the reference counter */ + deref_sched_response(Sched_INFO->sched_response_id); + stop_meas(&gNB->schedule_response_stats); } diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index cdbe21465f..317159f6bd 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -81,6 +81,17 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {} NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { return (NULL); } nfapi_mode_t nfapi_getmode(void) { return NFAPI_MODE_UNKNOWN; } +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + nrUE_params_t nrUE_params={0}; nrUE_params_t *get_nrUE_params(void) { diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index b2c9ac5a33..ce3c564773 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -328,7 +328,7 @@ int main(int argc, char **argv) //int frame_length_complex_samples_no_prefix; NR_DL_FRAME_PARMS *frame_parms; UE_nr_rxtx_proc_t UE_proc; - NR_Sched_Rsp_t Sched_INFO; + NR_Sched_Rsp_t *Sched_INFO; gNB_MAC_INST *gNB_mac; NR_UE_MAC_INST_t *UE_mac; int cyclic_prefix_type = NFAPI_CP_NORMAL; @@ -994,28 +994,33 @@ int main(int argc, char **argv) round = 0; UE_harq_process->DLround = round; UE_harq_process->first_rx = 1; - + + Sched_INFO = malloc(sizeof(*Sched_INFO)); + if (Sched_INFO == NULL) { + LOG_E(PHY, "out of memory\n"); + exit(1); + } + memset(Sched_INFO, 0, sizeof(*Sched_INFO)); + Sched_INFO->sched_response_id = -1; + while ((roundack==0)) { round_trials[round]++; - clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot); + clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req); UE_info->UE_sched_ctrl.harq_processes[harq_pid].ndi = !(trial&1); UE_info->UE_sched_ctrl.harq_processes[harq_pid].round = round; - nr_schedule_ue_spec(0, frame, slot); - Sched_INFO.module_id = 0; - Sched_INFO.CC_id = 0; - Sched_INFO.frame = frame; - Sched_INFO.slot = slot; - Sched_INFO.DL_req = &gNB_mac->DL_req[0]; - Sched_INFO.UL_tti_req = gNB_mac->UL_tti_req_ahead[0]; - Sched_INFO.UL_dci_req = NULL; - Sched_INFO.TX_req = &gNB_mac->TX_req[0]; + nr_schedule_ue_spec(0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req); + Sched_INFO->module_id = 0; + Sched_INFO->CC_id = 0; + Sched_INFO->frame = frame; + Sched_INFO->slot = slot; + Sched_INFO->UL_dci_req.numPdus = 0; pushNotifiedFIFO(&gNB->L1_tx_free,msgL1Tx); - nr_schedule_response(&Sched_INFO); + nr_schedule_response(Sched_INFO); /* PTRS values for DLSIM calculations */ - nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[Sched_INFO.CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &Sched_INFO->DL_req.dl_tti_request_body; nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1]; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; pdu_bit_map = pdsch_pdu_rel15->pduBitmap; diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index ee67e8d52e..5f254bc1cd 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -67,6 +67,17 @@ openair0_config_t openair0_cfg[MAX_CARDS]; uint8_t const nr_rv_round_map[4] = {0, 2, 3, 1}; +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + uint64_t get_softmodem_optmask(void) {return 0;} static softmodem_params_t softmodem_params; softmodem_params_t *get_softmodem_params(void) { diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 629b7316b0..aa441e4c61 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -86,6 +86,17 @@ softmodem_params_t *get_softmodem_params(void) {return 0;} instance_t DUuniqInstance=0; instance_t CUuniqInstance=0; +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star) { return 0; diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 01eec03c4d..a0631767ba 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -73,6 +73,17 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {} NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { return (NULL); } nfapi_mode_t nfapi_getmode(void) { return NFAPI_MODE_UNKNOWN; } +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + nrUE_params_t nrUE_params={0}; nrUE_params_t *get_nrUE_params(void) { diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 344f3f3310..69b12e78ee 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -80,6 +80,17 @@ PHY_VARS_NR_UE *PHY_vars_UE_g[1][1] = { { NULL } }; uint16_t n_rnti = 0x1234; openair0_config_t openair0_cfg[MAX_CARDS]; +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + int nr_postDecode_sim(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) { ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req); NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 109b4faf20..d8ffdcc55e 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -759,10 +759,10 @@ int main(int argc, char **argv) NR_gNB_ULSCH_t *ulsch_gNB = &gNB->ulsch[UE_id]; // nfapi_nr_ul_config_ulsch_pdu *rel15_ul = &ulsch_gNB->harq_process->ulsch_pdu; - nfapi_nr_ul_tti_request_t *UL_tti_req = malloc(sizeof(*UL_tti_req)); NR_Sched_Rsp_t *Sched_INFO = malloc(sizeof(*Sched_INFO)); memset((void*)Sched_INFO,0,sizeof(*Sched_INFO)); - Sched_INFO->UL_tti_req=UL_tti_req; + nfapi_nr_ul_tti_request_t *UL_tti_req = &Sched_INFO->UL_tti_req; + Sched_INFO->sched_response_id = -1; nr_phy_data_tx_t phy_data = {0}; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 41a2153cf8..c4ed4e2d2a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -56,10 +56,13 @@ const uint8_t nr_rv_round_map[4] = { 0, 2, 3, 1 }; uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 }; -void clear_nr_nfapi_information(gNB_MAC_INST * gNB, +void clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, frame_t frameP, - sub_frame_t slotP) + sub_frame_t slotP, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req, + nfapi_nr_ul_dci_request_t *UL_dci_req) { NR_ServingCellConfigCommon_t *scc = gNB->common_channels->ServingCellConfigCommon; @@ -67,10 +70,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, UL_tti_req_ahead_initialization(gNB, scc, num_slots, CC_idP, frameP, slotP, *scc->ssbSubcarrierSpacing); - nfapi_nr_dl_tti_request_t *DL_req = &gNB->DL_req[0]; nfapi_nr_dl_tti_pdcch_pdu_rel15_t **pdcch = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t **)gNB->pdcch_pdu_idx[CC_idP]; - nfapi_nr_ul_dci_request_t *UL_dci_req = &gNB->UL_dci_req[0]; - nfapi_nr_tx_data_request_t *TX_req = &gNB->TX_req[0]; gNB->pdu_index[CC_idP] = 0; @@ -96,23 +96,53 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, future_ul_tti_req->n_ulcch = 0; future_ul_tti_req->n_group = 0; - /* UL_tti_req is a simple pointer into the current UL_tti_req_ahead, i.e., - * it walks over UL_tti_req_ahead in a circular fashion */ - const int current_index = ul_buffer_index(frameP, slotP, *scc->ssbSubcarrierSpacing, gNB->UL_tti_req_ahead_size); - gNB->UL_tti_req[CC_idP] = &gNB->UL_tti_req_ahead[CC_idP][current_index]; TX_req[CC_idP].Number_of_PDUs = 0; - } bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) { return (bitmap >> (slot % 64)) & 0x01; } -void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, - frame_t frame, - sub_frame_t slot) +/* the structure nfapi_nr_ul_tti_request_t is very big, let's copy only what is necessary */ +static void copy_ul_tti_req(nfapi_nr_ul_tti_request_t *to, nfapi_nr_ul_tti_request_t *from) { + int i; + to->header = from->header; + to->SFN = from->SFN; + to->Slot = from->Slot; + to->n_pdus = from->n_pdus; + to->rach_present = from->rach_present; + to->n_ulsch = from->n_ulsch; + to->n_ulcch = from->n_ulcch; + to->n_group = from->n_group; + + for (i = 0; i < from->n_pdus; i++) { + to->pdus_list[i].pdu_type = from->pdus_list[i].pdu_type; + to->pdus_list[i].pdu_size = from->pdus_list[i].pdu_size; + + switch (from->pdus_list[i].pdu_type) { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + to->pdus_list[i].prach_pdu = from->pdus_list[i].prach_pdu; + break; + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + to->pdus_list[i].pusch_pdu = from->pdus_list[i].pusch_pdu; + break; + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + to->pdus_list[i].pucch_pdu = from->pdus_list[i].pucch_pdu; + break; + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: + to->pdus_list[i].srs_pdu = from->pdus_list[i].srs_pdu; + break; + } + } + + for (i = 0; i < from->n_group; i++) + to->groups_list[i] = from->groups_list[i]; +} + +void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_t slot, NR_Sched_Rsp_t *sched_info) +{ protocol_ctxt_t ctxt = {0}; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP); @@ -157,8 +187,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL; memcpy(&vrb_map_UL[prev_slot % size * MAX_BWP_SIZE], &gNB->ulprbbl, sizeof(uint16_t) * MAX_BWP_SIZE); - clear_nr_nfapi_information(gNB, CC_id, frame, slot); - + clear_nr_nfapi_information(gNB, CC_id, frame, slot, &sched_info->DL_req, &sched_info->TX_req, &sched_info->UL_dci_req); } if ((slot == 0) && (frame & 127) == 0) { @@ -172,12 +201,11 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, schedule_nr_bwp_switch(module_idP, frame, slot); // This schedules MIB - schedule_nr_mib(module_idP, frame, slot); + schedule_nr_mib(module_idP, frame, slot, &sched_info->DL_req); // This schedules SIB1 if (get_softmodem_params()->sa == 1) - schedule_nr_sib1(module_idP, frame, slot); - + schedule_nr_sib1(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req); // This schedule PRACH if we are not in phy_test mode if (get_softmodem_params()->phy_test == 0) { @@ -194,7 +222,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, } // Schedule CSI-RS transmission - nr_csirs_scheduling(module_idP, frame, slot, nr_slots_per_frame[*scc->ssbSubcarrierSpacing]); + nr_csirs_scheduling(module_idP, frame, slot, nr_slots_per_frame[*scc->ssbSubcarrierSpacing], &sched_info->DL_req); // Schedule CSI measurement reporting nr_csi_meas_reporting(module_idP, frame, slot); @@ -204,22 +232,29 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // This schedule RA procedure if not in phy_test mode // Otherwise consider 5G already connected if (get_softmodem_params()->phy_test == 0) { - nr_schedule_RA(module_idP, frame, slot); + nr_schedule_RA(module_idP, frame, slot, &sched_info->UL_dci_req, &sched_info->DL_req, &sched_info->TX_req); } // This schedules the DCI for Uplink and subsequently PUSCH - nr_schedule_ulsch(module_idP, frame, slot); + nr_schedule_ulsch(module_idP, frame, slot, &sched_info->UL_dci_req); // This schedules the DCI for Downlink and PDSCH start_meas(&gNB->schedule_dlsch); - nr_schedule_ue_spec(module_idP, frame, slot); + nr_schedule_ue_spec(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req); stop_meas(&gNB->schedule_dlsch); nr_sr_reporting(gNB, frame, slot); nr_schedule_pucch(gNB, frame, slot); + /* TODO: we copy from gNB->UL_tti_req_ahead[0][current_index], ie. CC_id == 0, + * is more than 1 CC supported? + */ + AssertFatal(MAX_NUM_CCs == 1, "only 1 CC supported\n"); + const int current_index = ul_buffer_index(frame, slot, *scc->ssbSubcarrierSpacing, gNB->UL_tti_req_ahead_size); + copy_ul_tti_req(&sched_info->UL_tti_req, &gNB->UL_tti_req_ahead[0][current_index]); + stop_meas(&gNB->eNB_scheduler); - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 587575241f..d08d2fefb3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -662,8 +662,13 @@ void nr_initiate_ra_proc(module_id_t module_idP, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); } -void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { - +void nr_schedule_RA(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_ul_dci_request_t *ul_dci_req, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ gNB_MAC_INST *mac = RC.nrmac[module_idP]; start_meas(&mac->schedule_ra); @@ -674,15 +679,15 @@ void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { LOG_D(NR_MAC, "RA[state:%d]\n", ra->state); switch (ra->state) { case Msg2: - nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); break; case Msg3_retransmission: - nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req); break; case Msg3_dcch_dtch: - nr_generate_Msg3_dcch_dtch_response(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg3_dcch_dtch_response(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); case Msg4: - nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); break; case WAIT_Msg4_ACK: nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra); @@ -695,9 +700,13 @@ void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { stop_meas(&mac->schedule_ra); } - -void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra) { - +void nr_generate_Msg3_retransmission(module_id_t module_idP, + int CC_id, + frame_t frame, + sub_frame_t slot, + NR_RA_t *ra, + nfapi_nr_ul_dci_request_t *ul_dci_req) +{ gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -784,8 +793,6 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t NR_ControlResourceSet_t *coreset = ra->coreset; AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg3 retransmission\n"); - nfapi_nr_ul_dci_request_t *ul_dci_req = &nr_mac->UL_dci_req[CC_id]; - const int coresetid = coreset->controlResourceSetId; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][coresetid]; if (!pdcch_pdu_rel15) { @@ -1148,8 +1155,14 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu); } -void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) { - +void nr_generate_Msg2(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP; @@ -1198,7 +1211,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra } // Checking if the DCI allocation is feasible in current subframe - nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, ra->RA_rnti); return; @@ -1369,7 +1382,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra nr_mac->cset0_bwp_size); // DL TX request - nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; // Program UL processing for Msg3 nr_get_Msg3alloc(module_idP, CC_id, scc, slotP, frameP, ra, nr_mac->tdd_beam_association); @@ -1395,9 +1408,9 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; tx_req->TLVs[0].length = tx_req->PDU_length + 2; - nr_mac->TX_req[CC_id].SFN = frameP; - nr_mac->TX_req[CC_id].Number_of_PDUs++; - nr_mac->TX_req[CC_id].Slot = slotP; + TX_req->SFN = frameP; + TX_req->Number_of_PDUs++; + TX_req->Slot = slotP; // Mark the corresponding symbols RBs as used fill_pdcch_vrb_map(nr_mac, @@ -1600,7 +1613,13 @@ void prepare_dl_pdus(gNB_MAC_INST *nr_mac, LOG_D(NR_MAC,"numDlDci: %i\n", pdcch_pdu_rel15->numDlDci); } -void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) +void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; @@ -1654,7 +1673,7 @@ void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, fram } // Checking if the DCI allocation is feasible in current subframe - nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, rnti); return; @@ -1734,15 +1753,15 @@ void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, fram 0, time_domain_assignment, CC_id, rnti, 0, mcsIndex, tb_scaling, pduindex, rbStart, rbSize); // DL TX request - nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; memcpy(tx_req->TLVs[0].value.direct, buf, sizeof(uint8_t) * tb_size); tx_req->PDU_length = tb_size; tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; tx_req->TLVs[0].length = tb_size + 2; - nr_mac->TX_req[CC_id].SFN = frameP; - nr_mac->TX_req[CC_id].Number_of_PDUs++; - nr_mac->TX_req[CC_id].Slot = slotP; + TX_req->SFN = frameP; + TX_req->Number_of_PDUs++; + TX_req->Slot = slotP; // Mark the corresponding symbols and RBs as used fill_pdcch_vrb_map(nr_mac, @@ -1780,7 +1799,13 @@ void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, fram sched_ctrl->ul_failure = 0; } -void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) +void nr_generate_Msg4(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; @@ -1854,7 +1879,7 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra } // Checking if the DCI allocation is feasible in current subframe - nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, ra->rnti); return; @@ -2006,15 +2031,15 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra T_INT(frameP), T_INT(slotP), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock, harq->tb_size)); // DL TX request - nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock, sizeof(uint8_t) * harq->tb_size); tx_req->PDU_length = harq->tb_size; tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; tx_req->TLVs[0].length = harq->tb_size + 2; - nr_mac->TX_req[CC_id].SFN = frameP; - nr_mac->TX_req[CC_id].Number_of_PDUs++; - nr_mac->TX_req[CC_id].Slot = slotP; + TX_req->SFN = frameP; + TX_req->Number_of_PDUs++; + TX_req->Slot = slotP; // Mark the corresponding symbols and RBs as used fill_pdcch_vrb_map(nr_mac, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 121ad179cc..37ceeddbee 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -89,10 +89,10 @@ void schedule_ssb(frame_t frame, sub_frame_t slot, } -void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { +void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, nfapi_nr_dl_tti_request_t *DL_req) +{ gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc; - nfapi_nr_dl_tti_request_t *dl_tti_request; nfapi_nr_dl_tti_request_body_t *dl_req; NR_MIB_t *mib = RC.nrrrc[module_idP]->carrier.mib.message.choice.mib; uint8_t num_tdd_period,num_ssb; @@ -103,8 +103,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) cc = &gNB->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; const int slots_per_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - dl_tti_request = &gNB->DL_req[CC_id]; - dl_req = &dl_tti_request->dl_tti_request_body; + dl_req = &DL_req->dl_tti_request_body; // get MIB every 8 frames if(((slotP == 0) && (frameP & 7) == 0) || @@ -255,7 +254,6 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) } } - void schedule_nr_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { //---------------------------------------- } @@ -520,8 +518,12 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, } -void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { - +void schedule_nr_sib1(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ // TODO: Get these values from RRC const int CC_id = 0; uint8_t candidate_idx = 0; @@ -586,12 +588,12 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) candidate_idx, sib1_sdu_length); - nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; int pdu_index = gNB_mac->pdu_index[0]++; nr_fill_nfapi_dl_sib1_pdu(module_idP, dl_req, pdu_index, type0_PDCCH_CSS_config, TBS, tda_info.startSymbolIndex, tda_info.nrOfSymbols); - const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs; - nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req]; + const int ntx_req = TX_req->Number_of_PDUs; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req]; // Data to be transmitted memcpy(tx_req->TLVs[0].value.direct, sib1_payload, TBS); @@ -600,9 +602,9 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) tx_req->PDU_index = pdu_index; tx_req->num_TLV = 1; tx_req->TLVs[0].length = TBS + 2; - gNB_mac->TX_req[CC_id].Number_of_PDUs++; - gNB_mac->TX_req[CC_id].SFN = frameP; - gNB_mac->TX_req[CC_id].Slot = slotP; + TX_req->Number_of_PDUs++; + TX_req->SFN = frameP; + TX_req->Slot = slotP; type0_PDCCH_CSS_config->active = false; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 7d3cd511e9..e6f32b1405 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -873,8 +873,10 @@ nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(int CC_id) { void nr_schedule_ue_spec(module_id_t module_id, frame_t frame, - sub_frame_t slot) { - + sub_frame_t slot, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; if (!is_xlsch_in_slot(gNB_mac->dlsch_slot_bitmap[slot / 64], slot)) @@ -885,7 +887,7 @@ void nr_schedule_ue_spec(module_id_t module_id, 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 = &gNB_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; UE_iterator(UE_info->list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -1326,16 +1328,16 @@ void nr_schedule_ue_spec(module_id_t module_id, T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock, TBS)); } - const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs; - nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req]; + const int ntx_req = TX_req->Number_of_PDUs; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req]; tx_req->PDU_length = TBS; tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; tx_req->TLVs[0].length = TBS + 2; memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock, TBS); - gNB_mac->TX_req[CC_id].Number_of_PDUs++; - gNB_mac->TX_req[CC_id].SFN = frame; - gNB_mac->TX_req[CC_id].Slot = slot; + TX_req->Number_of_PDUs++; + TX_req->SFN = frame; + TX_req->Slot = slot; /* mark UE as scheduled */ sched_pdsch->rbSize = 0; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 09d4d95458..99ce0ab235 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2538,11 +2538,8 @@ int get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config, } } -void nr_csirs_scheduling(int Mod_idP, - frame_t frame, - sub_frame_t slot, - int n_slots_frame){ - +void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slots_frame, nfapi_nr_dl_tti_request_t *DL_req) +{ int CC_id = 0; NR_UEs_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP]; @@ -2581,7 +2578,7 @@ void nr_csirs_scheduling(int Mod_idP, NR_NZP_CSI_RS_Resource_t *nzpcsi; int period, offset; - nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; for (int id = 0; id < csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count; id++){ nzpcsi = csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.array[id]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 09aad3d9cb..3c314c6c86 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1997,7 +1997,7 @@ nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(int CC_id) return nr_fr1_ulsch_preprocessor; } -void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) +void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, nfapi_nr_ul_dci_request_t *ul_dci_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; /* Uplink data ONLY can be scheduled when the current slot is downlink slot, @@ -2010,8 +2010,6 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) if (!do_sched) return; - const int CC_id = 0; - nfapi_nr_ul_dci_request_t *ul_dci_req = &nr_mac->UL_dci_req[CC_id]; ul_dci_req->SFN = frame; ul_dci_req->Slot = slot; /* a PDCCH PDU groups DCIs per BWP and CORESET. Save a pointer to each diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index b62984943c..a700c5c652 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -60,17 +60,19 @@ bool nr_mac_prepare_ra_nsa_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupCo bool nr_mac_update_cellgroup(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); bool nr_mac_update_RA(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); -void clear_nr_nfapi_information(gNB_MAC_INST * gNB, +void clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, - frame_t frameP, - sub_frame_t subframeP); + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req, + nfapi_nr_ul_dci_request_t *UL_dci_req); void nr_mac_update_timers(module_id_t module_id, frame_t frame, sub_frame_t slot); -void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, - frame_t frame_rxP, sub_frame_t slot_rxP); +void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame_rxP, sub_frame_t slot_rxP, NR_Sched_Rsp_t *sched_info); void schedule_nr_bwp_switch(module_id_t module_id, frame_t frame, @@ -81,7 +83,9 @@ void schedule_nr_bwp_switch(module_id_t module_id, * messages, statistics, HARQ handling, CEs, ... */ void nr_schedule_ue_spec(module_id_t module_id, frame_t frame, - sub_frame_t slot); + sub_frame_t slot, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); uint32_t schedule_control_sib1(module_id_t module_id, int CC_id, @@ -95,21 +99,30 @@ uint32_t schedule_control_sib1(module_id_t module_id, /* \brief default FR1 DL preprocessor init routine, returns preprocessor to call */ nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(int CC_id); -void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); +void schedule_nr_sib1(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); -void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); +void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, nfapi_nr_dl_tti_request_t *DL_req); /* \brief main UL scheduler function. Calls a preprocessor to decide on * resource allocation, then "post-processes" resource allocation (nFAPI * messages, statistics, HARQ handling, ... */ -void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot); +void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, nfapi_nr_ul_dci_request_t *ul_dci_req); /* \brief default FR1 UL preprocessor init routine, returns preprocessor to call */ nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(int CC_id); /////// Random Access MAC-PHY interface functions and primitives /////// -void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); +void nr_schedule_RA(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_ul_dci_request_t *ul_dci_req, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); /* \brief Function to indicate a received preamble on PRACH. It initiates the RA procedure. @param module_idP Instance ID of gNB @@ -134,7 +147,12 @@ void nr_get_Msg3alloc(module_id_t module_id, NR_RA_t *ra, int16_t *tdd_beam_association); -void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); +void nr_generate_Msg3_retransmission(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_ul_dci_request_t *ul_dci_req); /* \brief Function in gNB to fill RAR pdu when requested by PHY. @param ra Instance of RA resources of gNB @@ -201,10 +219,7 @@ void nr_srs_ri_computation(const nfapi_nr_srs_normalized_channel_iq_matrix_t *nr void nr_schedule_srs(int module_id, frame_t frame, int slot); -void nr_csirs_scheduling(int Mod_idP, - frame_t frame, - sub_frame_t slot, - int n_slots_frame); +void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slots_frame, nfapi_nr_dl_tti_request_t *DL_req); void nr_csi_meas_reporting(int Mod_idP, frame_t frameP, @@ -365,13 +380,31 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, unsigned char drx_cmd, unsigned char *ue_cont_res_id); -void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); +void nr_generate_Msg2(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *dl_req, + nfapi_nr_tx_data_request_t *TX_req); -void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); +void nr_generate_Msg4(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra); -void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); +void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); int binomial(int n, int k); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 96734aa8b1..1cd0f89736 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -719,24 +719,15 @@ typedef struct gNB_MAC_INST_s { uint16_t ulprbbl[MAX_BWP_SIZE]; /// NFAPI Config Request Structure nfapi_nr_config_request_scf_t config[NFAPI_CC_MAX]; - /// NFAPI DL Config Request Structure - nfapi_nr_dl_tti_request_t DL_req[NFAPI_CC_MAX]; /// a PDCCH PDU groups DCIs per BWP and CORESET. The following structure /// keeps pointers to PDCCH PDUs within DL_req so that we can easily track /// PDCCH PDUs per CC/BWP/CORESET nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_idx[NFAPI_CC_MAX][MAX_NUM_CORESET]; - /// NFAPI UL TTI Request Structure, simple pointer into structure - /// UL_tti_req_ahead for current frame/slot - nfapi_nr_ul_tti_request_t *UL_tti_req[NFAPI_CC_MAX]; /// NFAPI UL TTI Request Structure for future TTIs, dynamically allocated /// because length depends on number of slots nfapi_nr_ul_tti_request_t *UL_tti_req_ahead[NFAPI_CC_MAX]; int UL_tti_req_ahead_size; int vrb_map_UL_size; - /// NFAPI HI/DCI0 Config Request Structure - nfapi_nr_ul_dci_request_t UL_dci_req[NFAPI_CC_MAX]; - /// NFAPI DL PDU structure - nfapi_nr_tx_data_request_t TX_req[NFAPI_CC_MAX]; NR_UEs_t UE_info; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 60db353949..117b028c9a 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -39,12 +39,12 @@ #include "nfapi/oai_integration/vendor_ext.h" #include "nfapi/oai_integration/gnb_ind_vars.h" #include "openair2/PHY_INTERFACE/queue_t.h" +#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" #define MAX_IF_MODULES 100 //#define UL_HARQ_PRINT static NR_IF_Module_t *nr_if_inst[MAX_IF_MODULES]; -static NR_Sched_Rsp_t NR_Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs]; extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind); extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind); extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind); @@ -389,7 +389,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { AssertFatal(UL_info!=NULL,"UL_info is null\n"); module_id_t module_id = UL_info->module_id; int CC_id = UL_info->CC_id; - NR_Sched_Rsp_t *sched_info = &NR_Sched_INFO[module_id][CC_id]; + NR_Sched_Rsp_t *sched_info; NR_IF_Module_t *ifi = nr_if_inst[module_id]; LOG_D(NR_PHY,"SFN/SLOT:%d.%d module_id:%d CC_id:%d UL_info[rach_pdus:%zu rx_ind:%zu crcs:%zu]\n", @@ -451,8 +451,6 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { } if (NFAPI_MODE != NFAPI_MODE_PNF) { gNB_MAC_INST *mac = RC.nrmac[module_id]; - // clear UL DCI prior to handling ULSCH - mac->UL_dci_req[CC_id].numPdus = 0; if (ifi->CC_mask==0) { ifi->current_frame = UL_info->frame; ifi->current_slot = UL_info->slot; @@ -471,21 +469,20 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { */ nfapi_nr_config_request_scf_t *cfg = &mac->config[CC_id]; int spf = get_spf(cfg); + sched_info = allocate_sched_response(); + // clear UL DCI prior to handling ULSCH + sched_info->UL_dci_req.numPdus = 0; gNB_dlsch_ulsch_scheduler(module_id, - (UL_info->frame+((UL_info->slot>(spf-1-ifi->sl_ahead))?1:0)) % 1024, - (UL_info->slot+ifi->sl_ahead)%spf); + (UL_info->frame + ((UL_info->slot > (spf - 1 - ifi->sl_ahead)) ? 1 : 0)) % 1024, + (UL_info->slot + ifi->sl_ahead) % spf, + sched_info); ifi->CC_mask = 0; sched_info->module_id = module_id; sched_info->CC_id = CC_id; sched_info->frame = (UL_info->frame + ((UL_info->slot>(spf-1-ifi->sl_ahead)) ? 1 : 0)) % 1024; sched_info->slot = (UL_info->slot+ifi->sl_ahead)%spf; - sched_info->DL_req = &mac->DL_req[CC_id]; - sched_info->UL_dci_req = &mac->UL_dci_req[CC_id]; - sched_info->UL_tti_req = mac->UL_tti_req[CC_id]; - - sched_info->TX_req = &mac->TX_req[CC_id]; #ifdef DUMP_FAPI dump_dl(sched_info); #endif @@ -496,10 +493,11 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { CC_id); ifi->NR_Schedule_response(sched_info); - LOG_D(NR_PHY,"NR_Schedule_response: SFN SLOT:%d %d dl_pdus:%d\n", - sched_info->frame, - sched_info->slot, - sched_info->DL_req->dl_tti_request_body.nPDUs); + LOG_D(NR_PHY, + "NR_Schedule_response: SFN SLOT:%d %d dl_pdus:%d\n", + sched_info->frame, + sched_info->slot, + sched_info->DL_req.dl_tti_request_body.nPDUs); } } } @@ -520,5 +518,7 @@ NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { "allocation of nr_if_inst[%d]->if_mutex fails\n",Mod_id); } + init_sched_response(); + return nr_if_inst[Mod_id]; } diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_PHY_INTERFACE/NR_IF_Module.h index 47e961da2b..f85d44398f 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.h @@ -83,6 +83,8 @@ typedef struct { typedef struct { + /// the ID of this sched_response - used by sched_reponse memory management + int sched_response_id; /// Module ID module_id_t module_id; /// CC ID @@ -92,13 +94,13 @@ typedef struct { /// slot slot_t slot; /// nFAPI DL Config Request - nfapi_nr_dl_tti_request_t *DL_req; + nfapi_nr_dl_tti_request_t DL_req; /// nFAPI UL Config Request - nfapi_nr_ul_tti_request_t *UL_tti_req; + nfapi_nr_ul_tti_request_t UL_tti_req; /// nFAPI UL_DCI Request - nfapi_nr_ul_dci_request_t *UL_dci_req; + nfapi_nr_ul_dci_request_t UL_dci_req; /// Pointers to DL SDUs - nfapi_nr_tx_data_request_t *TX_req; + nfapi_nr_tx_data_request_t TX_req; } NR_Sched_Rsp_t; typedef struct { diff --git a/openair2/NR_PHY_INTERFACE/nr_sched_response.c b/openair2/NR_PHY_INTERFACE/nr_sched_response.c new file mode 100644 index 0000000000..f0aa25781c --- /dev/null +++ b/openair2/NR_PHY_INTERFACE/nr_sched_response.c @@ -0,0 +1,153 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* sched response memory management */ + +/* A system with reference counting is implemented. + * It is needed because several threads will access the structure, + * which has to be released only when all the threads are done with it. + * So the main thread allocates a sched_response with allocate_sched_response() + * which allocates a sched_response with a reference counter == 1 + * and then for each other thread that will access sched_response, a + * call to inc_ref_sched_response() is done. When a thread has finished + * using the sched_response, it calls deref_sched_response() which will + * in turn call release_sched_response() when the reference counter becomes 0. + * + * The several threads in question are accessing the _same_ sched_response, + * it has not to be confused with the various TX processes that may run in + * parallel and which are accessing _different_ sched_response (the maximum + * number of parallel processes is N_RESP). + */ + +#include "nr_sched_response.h" + +#include +#include + +#include "common/utils/LOG/log.h" +#include "common/utils/assertions.h" + +#define N_RESP 3 +static NR_Sched_Rsp_t resp[N_RESP]; +static int resp_refcount[N_RESP]; +static int resp_freelist_next[N_RESP]; +static int resp_freelist_head; +static pthread_mutex_t resp_mutex = PTHREAD_MUTEX_INITIALIZER; +static bool resp_freelist_inited = false; + +void init_sched_response(void) +{ + /* init only once */ + if (pthread_mutex_lock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_lock failed\n"); + if (resp_freelist_inited) { + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); + return; + } + resp_freelist_inited = true; + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); + + int i; + for (i = 0; i < N_RESP - 1; i++) + resp_freelist_next[i] = i + 1; + resp_freelist_next[N_RESP - 1] = -1; + resp_freelist_head = 0; +} + +NR_Sched_Rsp_t *allocate_sched_response(void) +{ + NR_Sched_Rsp_t *ret; + int new_head; + + if (pthread_mutex_lock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_lock failed\n"); + + AssertFatal(resp_freelist_inited, "sched_response used before init\n"); + + if (resp_freelist_head == -1) { + LOG_E(PHY, "fatal: sched_response cannot be allocated, increase N_RESP\n"); + exit(1); + } + + ret = &resp[resp_freelist_head]; + ret->sched_response_id = resp_freelist_head; + resp_refcount[resp_freelist_head] = 1; + + new_head = resp_freelist_next[resp_freelist_head]; + resp_freelist_next[resp_freelist_head] = -1; + resp_freelist_head = new_head; + + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); + + return ret; +} + +static void release_sched_response(int sched_response_id) +{ + resp_freelist_next[sched_response_id] = resp_freelist_head; + resp_freelist_head = sched_response_id; +} + +void deref_sched_response(int sched_response_id) +{ + /* simulators (ulsim/dlsim) deal with their own sched_response but call + * functions that call this one, let's handle this case with a special + * value -1 where we do nothing (yes it's a hack) + */ + if (sched_response_id == -1) + return; + + if (pthread_mutex_lock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_lock failed\n"); + + AssertFatal(resp_freelist_inited, "sched_response used before init\n"); + AssertFatal(resp_refcount[sched_response_id] > 0, "sched_reponse decreased too much\n"); + + resp_refcount[sched_response_id]--; + if (resp_refcount[sched_response_id] == 0) + release_sched_response(sched_response_id); + + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); +} + +void inc_ref_sched_response(int sched_response_id) +{ + /* simulators (ulsim/dlsim) deal with their own sched_response but call + * functions that call this one, let's handle this case with a special + * value -1 where we do nothing (yes it's a hack) + */ + if (sched_response_id == -1) + return; + + if (pthread_mutex_lock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_lock failed\n"); + + AssertFatal(resp_freelist_inited, "sched_response used before init\n"); + + resp_refcount[sched_response_id]++; + + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); +} diff --git a/openair2/NR_PHY_INTERFACE/nr_sched_response.h b/openair2/NR_PHY_INTERFACE/nr_sched_response.h new file mode 100644 index 0000000000..33a0af93d0 --- /dev/null +++ b/openair2/NR_PHY_INTERFACE/nr_sched_response.h @@ -0,0 +1,32 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H +#define OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H + +#include "NR_IF_Module.h" + +void init_sched_response(void); +NR_Sched_Rsp_t *allocate_sched_response(void); +void deref_sched_response(int sched_response_id); +void inc_ref_sched_response(int sched_response_id); + +#endif /* OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H */