Commit 733c7e5e authored by Cedric Roux's avatar Cedric Roux

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.)
parent 1f979696
......@@ -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
......
......@@ -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)
......
......@@ -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
......@@ -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;i<number_dl_pdu;i++) {
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu = &DL_req->dl_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; i<number_ul_dci_pdu; i++)
msgTx->ul_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);
}
......@@ -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) {
......
......@@ -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 ((round<num_rounds) && (UE_harq_process->ack==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;
......
......@@ -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) {
......
......@@ -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;
......
......@@ -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) {
......
......@@ -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;
......
......@@ -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};
......
......@@ -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);
}
......@@ -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,
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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];
......
......@@ -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
......
......@@ -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);
......
......@@ -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;
......
......@@ -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];
}
......@@ -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 {
......
/*
* 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 <pthread.h>
#include <stdlib.h>
#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");
}
/*
* 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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment