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 */