From bc6f39370c1ca1f73ca863e16ca832e37367fc60 Mon Sep 17 00:00:00 2001
From: Sakthivel Velumani <velumani@eurecom.fr>
Date: Wed, 7 Jul 2021 09:19:14 +0200
Subject: [PATCH] Added checks if tx RU processing start in order

---
 executables/nr-gnb.c                      |  49 +++++++---
 executables/nr-ru.c                       |  32 ++-----
 openair1/PHY/INIT/nr_init.c               |  27 ++----
 openair1/PHY/NR_TRANSPORT/nr_dci_tools.c  | 104 ----------------------
 openair1/PHY/NR_TRANSPORT/nr_dlsch.h      |   2 +-
 openair1/PHY/defs_RU.h                    |   1 +
 openair1/PHY/defs_gNB.h                   |  12 ++-
 openair1/SCHED_NR/fapi_nr_l1.c            |  40 ++-------
 openair1/SCHED_NR/phy_frame_config_nr.c   |  16 ++++
 openair1/SCHED_NR/phy_frame_config_nr.h   |   2 +
 openair1/SCHED_NR/phy_procedures_nr_gNB.c |  27 +++---
 openair1/SCHED_NR/sched_nr.h              |   2 +-
 12 files changed, 101 insertions(+), 213 deletions(-)

diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c
index 2bbabf3fe0..ef1d4e22fa 100644
--- a/executables/nr-gnb.c
+++ b/executables/nr-gnb.c
@@ -122,20 +122,27 @@ void tx_func(void *param) {
                         frame_tx,
                         slot_tx,
                         1);
+  info->status = NOT_FILLED;
   if ((frame_tx&127) == 0) dump_pdsch_stats(gNB);
 
   // If the later of the 2 L1 tx thread finishes first,
   // we wait for the earlier one to finish and start the RU thread
   // to avoid realtime issues with USRP
-  notifiedFIFO_elt_t *res; 
-  res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
-  pushNotifiedFIFO(gNB->resp_L1_tx,res);
 
   // Start RU TX processing.
+  notifiedFIFO_elt_t *res;
   res = pullTpool(gNB->resp_RU_tx, gNB->threadPool);
   processingData_RU_t *syncMsg = (processingData_RU_t *)NotifiedFifoData(res);
+  LOG_D(PHY,"waiting for previous tx to finish, next slot %d,%d\n",syncMsg->next_slot,slot_tx);
+  while (syncMsg->next_slot != slot_tx) {
+    pushNotifiedFIFO(gNB->resp_RU_tx, res);
+    res = pullTpool(gNB->resp_RU_tx, gNB->threadPool);
+    syncMsg = (processingData_RU_t *)NotifiedFifoData(res);
+  }
+  LOG_D(PHY,"previous tx to finished, next slot %d,%d\n",syncMsg->next_slot,slot_tx);
   syncMsg->frame_tx = frame_tx;
   syncMsg->slot_tx = slot_tx;
+  syncMsg->next_slot = get_next_downlink_slot(gNB, &gNB->gNB_config, frame_tx, slot_tx);
   syncMsg->timestamp_tx = info->timestamp_tx;
   syncMsg->ru = gNB->RU_list[0];
   res->key = slot_tx;
@@ -213,13 +220,6 @@ void rx_func(void *param) {
         }
         up_removed++;
       }
-    for (j = 0; j < NUMBER_OF_NR_DLSCH_MAX; j++)
-      if (gNB->dlsch[j][0]->rnti == rnti_to_remove[i]) {
-        gNB->dlsch[j][0]->rnti = 0;
-        gNB->dlsch[j][0]->harq_mask = 0;
-        //clean_gNB_dlsch(gNB->dlsch[j][0]);
-        down_removed++;
-      }
     for (j = 0; j < NUMBER_OF_NR_PUCCH_MAX; j++)
       if (gNB->pucch[j]->active > 0 &&
           gNB->pucch[j]->pucch_pdu.rnti == rnti_to_remove[i]) {
@@ -277,10 +277,15 @@ void rx_func(void *param) {
   pthread_mutex_unlock(&gNB->UL_INFO_mutex);
   stop_meas(&gNB->ul_indication_stats);
   
-  notifiedFIFO_elt_t *res; 
   if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) {
+    notifiedFIFO_elt_t *res;
     res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
     processingData_L1tx_t *syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
+    while (syncMsg->status == NOT_FILLED) {
+      pushNotifiedFIFO(gNB->resp_L1_tx, res);
+      res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
+      syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
+    }
     syncMsg->gNB = gNB;
     syncMsg->frame_rx = frame_rx;
     syncMsg->slot_rx = slot_rx;
@@ -400,14 +405,36 @@ void init_gNB_Tpool(int inst) {
   // L1 RX result FIFO 
   gNB->resp_L1 = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
   initNotifiedFIFO(gNB->resp_L1);
+  notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1,rx_func);
+  pushNotifiedFIFO(gNB->resp_L1,msg); // to unblock the process in the beginning
 
   // L1 TX result FIFO 
   gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
   initNotifiedFIFO(gNB->resp_L1_tx);
+  // we create 2 threads for L1 tx processing
+  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,tx_func);
+  processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
+  init_DLSCH_struct(gNB, msgDataTx);
+  memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
+  reset_meas(&msgDataTx->phy_proc_tx);
+  gNB->phy_proc_tx_0 = &msgDataTx->phy_proc_tx;
+  pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
+
+  msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,tx_func);
+  msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
+  init_DLSCH_struct(gNB, msgDataTx);
+  memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
+  reset_meas(&msgDataTx->phy_proc_tx);
+  gNB->phy_proc_tx_1 = &msgDataTx->phy_proc_tx;
+  pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
 
   // RU TX result FIFO 
   gNB->resp_RU_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
   initNotifiedFIFO(gNB->resp_RU_tx);
+  notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_RU_t),0,gNB->resp_RU_tx,ru_tx_func);
+  processingData_RU_t *msgData = (processingData_RU_t*)msgRUTx->msgData;
+  msgData->next_slot = sf_ahead*gNB->frame_parms.slots_per_subframe; // first Tx slot
+  pushNotifiedFIFO(gNB->resp_RU_tx,msgRUTx); // to unblock the process in the beginning
 
   // Stats measurement thread
   if(opp_enabled == 1) threadCreate(&proc->process_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW);
diff --git a/executables/nr-ru.c b/executables/nr-ru.c
index a01be1ebaa..40acf97285 100644
--- a/executables/nr-ru.c
+++ b/executables/nr-ru.c
@@ -1269,30 +1269,9 @@ void *ru_thread( void *param ) {
   pthread_mutex_unlock(&RC.ru_mutex);
   wait_sync("ru_thread");
 
-  notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1,rx_func);
-  pushNotifiedFIFO(gNB->resp_L1,msg); // to unblock the process in the beginning
-
-  // we create 2 threads for L1 tx processing
-  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,tx_func);
-  processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
-  init_DLSCH_struct(gNB, msgDataTx);
-  reset_meas(&msgDataTx->phy_proc_tx);
-  gNB->phy_proc_tx_0 = &msgDataTx->phy_proc_tx;
-  pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
-
-  msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,tx_func);
-  msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
-  init_DLSCH_struct(gNB, msgDataTx);
-  reset_meas(&msgTx->phy_proc_tx);
-  gNB->phy_proc_tx_1 = &msgDataTx->phy_proc_tx;
-  pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
-
   processingData_L1_t *syncMsg;
   notifiedFIFO_elt_t *res;
 
-  notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_RU_tx,ru_tx_func);
-  pushNotifiedFIFO(gNB->resp_RU_tx,msgRUTx); // to unblock the process in the beginning
-
   if(!emulate_rf) {
     // Start RF device if any
     if (ru->start_rf) {
@@ -1423,9 +1402,14 @@ void *ru_thread( void *param ) {
     else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx);
   }
 
-  delNotifiedFIFO_elt(msg);
-  delNotifiedFIFO_elt(msgL1Tx);
-  delNotifiedFIFO_elt(msgRUTx);
+  res = pullNotifiedFIFO(gNB->resp_L1);
+  delNotifiedFIFO_elt(res);
+  res = pullNotifiedFIFO(gNB->resp_L1_tx);
+  delNotifiedFIFO_elt(res);
+  res = pullNotifiedFIFO(gNB->resp_L1_tx);
+  delNotifiedFIFO_elt(res);
+  res = pullNotifiedFIFO(gNB->resp_RU_tx);
+  delNotifiedFIFO_elt(res);
 
   ru_thread_status = 0;
   return &ru_thread_status;
diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c
index bdbd2df92c..d2347bd3df 100644
--- a/openair1/PHY/INIT/nr_init.c
+++ b/openair1/PHY/INIT/nr_init.c
@@ -547,14 +547,14 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) {
 }
 
 void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg) {
-  NR_DL_FRAME_PARMS *fp = &msg->gNB->frame_parms;
-  nfapi_nr_config_request_scf_t *cfg = &msg->gNB->gNB_config;
+  NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
+  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
   uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value;
-  memset(msg->num_pdsch_rnti, 0, sizeof(uint16_t)*80);
+  msg->num_pdsch_slot = 0;
 
-  for (i=0; i<gNB->number_of_nr_dlsch_max; i++) {
-    LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH %d/%d\n",i,number_of_nr_dlsch_max);
-    for (j=0; j<2; j++) {
+  for (int i=0; i<gNB->number_of_nr_dlsch_max; i++) {
+    LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH %d/%d\n",i,gNB->number_of_nr_dlsch_max);
+    for (int j=0; j<2; j++) {
       msg->dlsch[i][j] = new_gNB_dlsch(fp,1,16,NSOFT,0,grid_size);
       AssertFatal(msg->dlsch[i][j]!=NULL,"Can't initialize dlsch %d \n", i);
     }
@@ -562,8 +562,6 @@ void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg) {
 }
 
 void init_nr_transport(PHY_VARS_gNB *gNB) {
-  int i;
-  int j;
   NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
   nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
   LOG_I(PHY, "Initialise nr transport\n");
@@ -571,24 +569,17 @@ void init_nr_transport(PHY_VARS_gNB *gNB) {
 
   memset(gNB->num_pdsch_rnti, 0, sizeof(uint16_t)*80);
 
-  for (i=0; i <NUMBER_OF_NR_PDCCH_MAX; i++) {
-    LOG_I(PHY,"Initializing PDCCH list for PDCCH %d/%d\n",i,NUMBER_OF_NR_PDCCH_MAX);
-    gNB->pdcch_pdu[i].frame=-1;
-    LOG_I(PHY,"Initializing UL PDCCH list for UL PDCCH %d/%d\n",i,NUMBER_OF_NR_PDCCH_MAX);
-    gNB->ul_pdcch_pdu[i].frame=-1;
-  }
-    
-  for (i=0; i<NUMBER_OF_NR_PUCCH_MAX; i++) {
+  for (int i=0; i<NUMBER_OF_NR_PUCCH_MAX; i++) {
     LOG_I(PHY,"Allocating Transport Channel Buffers for PUCCH %d/%d\n",i,NUMBER_OF_NR_PUCCH_MAX);
     gNB->pucch[i] = new_gNB_pucch();
     AssertFatal(gNB->pucch[i]!=NULL,"Can't initialize pucch %d \n", i);
   }
 
-  for (i=0; i<gNB->number_of_nr_ulsch_max; i++) {
+  for (int i=0; i<gNB->number_of_nr_ulsch_max; i++) {
 
     LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH  %d/%d\n",i,gNB->number_of_nr_ulsch_max);
 
-    for (j=0; j<2; j++) {
+    for (int j=0; j<2; j++) {
       // ULSCH for data
       gNB->ulsch[i][j] = new_gNB_ulsch(MAX_LDPC_ITERATIONS, fp->N_RB_UL, 0);
 
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c
index c562dfaa41..770c35105f 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c
@@ -202,107 +202,3 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m,  nfapi_nr_dl_tti_pdcch_pdu_r
     ret |= ((field>>i)&1)<<(size-i-1);
   return ret;
 }*/
-int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type) {
-
-  uint16_t i;
-  int16_t first_free_index=-1;
-
-  AssertFatal(gNB!=NULL,"gNB is null\n");
-  for (i=0; i<NUMBER_OF_NR_PDCCH_MAX; i++) {
-    LOG_D(PHY,"searching for frame.slot %d.%d : pdcch_index %d frame.slot %d.%d, first_free_index %d\n", frame,slot,i,gNB->pdcch_pdu[i].frame,gNB->pdcch_pdu[i].slot,first_free_index);
-    if ((gNB->pdcch_pdu[i].frame == frame) &&
-        (gNB->pdcch_pdu[i].slot==slot))       return i;
-    else if ( gNB->pdcch_pdu[i].frame==-1 && first_free_index==-1) first_free_index=i;
-  }
-  if (type == SEARCH_EXIST) return -1;
-
-  return first_free_index;
-}
-
-
-void nr_fill_dci(PHY_VARS_gNB *gNB,
-                 int frame,
-                 int slot,
-		 nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu) {
-
-  nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu_rel15;
-  NR_gNB_DLSCH_t *dlsch; 
-
-  int pdcch_id = find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST_OR_FREE);
-  AssertFatal(pdcch_id>=0 && pdcch_id<NUMBER_OF_NR_PDCCH_MAX,"Cannot find space for PDCCH, exiting\n");
-  memcpy((void*)&gNB->pdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu));
-  gNB->pdcch_pdu[pdcch_id].frame = frame;
-  gNB->pdcch_pdu[pdcch_id].slot  = slot;
-
-  for (int i=0;i<pdcch_pdu_rel15->numDlDci;i++) {
-
-    //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu[i].Payload;
-
-    int dlsch_id = find_nr_dlsch(pdcch_pdu_rel15->dci_pdu[i].RNTI,gNB,SEARCH_EXIST_OR_FREE);
-    if( (dlsch_id<0) || (dlsch_id>=gNB->number_of_nr_dlsch_max) ){
-      LOG_E(PHY,"illegal dlsch_id found!!! rnti %04x dlsch_id %d\n",(unsigned int)pdcch_pdu_rel15->dci_pdu[i].RNTI,dlsch_id);
-      return;
-    }
-    
-    dlsch = gNB->dlsch[dlsch_id][0];
-    int harq_pid = 0;
-
-    dlsch->slot_tx[slot]             = 1;
-    dlsch->harq_ids[frame % 2][slot] = 0;
-    AssertFatal(harq_pid < 8 && harq_pid >= 0,
-		"illegal harq_pid %d\n",harq_pid);
-    
-    dlsch->harq_mask                |= (1<<harq_pid);
-    dlsch->rnti                      = pdcch_pdu_rel15->dci_pdu[i].RNTI;
-    
-    //    nr_fill_cce_list(gNB,0);
-  }
-
-}
-
-
-int16_t find_nr_ul_dci(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type) {
-
-  uint16_t i;
-  int16_t first_free_index=-1;
-
-  AssertFatal(gNB!=NULL,"gNB is null\n");
-  for (i=0; i<NUMBER_OF_NR_PDCCH_MAX; i++) {
-    LOG_D(PHY,"searching for frame.slot %d.%d : ul_pdcch_index %d frame.slot %d.%d, first_free_index %d\n", frame,slot,i,gNB->ul_pdcch_pdu[i].frame,gNB->ul_pdcch_pdu[i].slot,first_free_index);
-    if ((gNB->ul_pdcch_pdu[i].frame == frame) &&
-        (gNB->ul_pdcch_pdu[i].slot==slot))       return i;
-    else if (gNB->ul_pdcch_pdu[i].frame==-1 && first_free_index==-1) first_free_index=i;
-  }
-  if (type == SEARCH_EXIST) return -1;
-
-  return first_free_index;
-}
-
-
-void nr_fill_ul_dci(PHY_VARS_gNB *gNB,
-		    int frame,
-		    int slot,
-		    nfapi_nr_ul_dci_request_pdus_t *pdcch_pdu) {
-
-  nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
-
-  int pdcch_id = find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST_OR_FREE);
-  AssertFatal(pdcch_id>=0 && pdcch_id<NUMBER_OF_NR_PDCCH_MAX,"Cannot find space for UL PDCCH, exiting\n");
-  memcpy((void*)&gNB->ul_pdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu));
-  gNB->ul_pdcch_pdu[pdcch_id].frame = frame;
-  gNB->ul_pdcch_pdu[pdcch_id].slot  = slot;
-
-  for (int i=0;i<pdcch_pdu_rel15->numDlDci;i++) {
-
-    //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu[i].Payload;
-
-    // if there's no DL DCI then generate CCE list
-    //    nr_fill_cce_list(gNB,0);  
-    /*
-    LOG_D(PHY, "DCI PDU: [0]->0x%lx \t [1]->0x%lx \n",dci_pdu[0], dci_pdu[1]);
-    LOG_D(PHY, "DCI type %d payload (size %d) generated on candidate %d\n", dci_alloc->pdcch_params.dci_format, dci_alloc->size, cand_idx);
-    */
-
-  }
-
-}
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h
index 9f03d34261..f773b99548 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h
@@ -67,7 +67,7 @@ void nr_fill_dlsch(processingData_L1tx_t *msgTx,
                    nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
                    unsigned char *sdu); 
 
-uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
+uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
 			  int frame,
 			  int slot);
 void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB);
diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h
index 66cb51adc6..76dd92ef5d 100644
--- a/openair1/PHY/defs_RU.h
+++ b/openair1/PHY/defs_RU.h
@@ -762,6 +762,7 @@ typedef struct RRU_config_s {
 typedef struct processingData_RU {
   int frame_tx;
   int slot_tx;
+  int next_slot;
   openair0_timestamp timestamp_tx;
   RU_t *ru;
 } processingData_RU_t;
diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h
index 9aea468a0d..b11f902dd2 100644
--- a/openair1/PHY/defs_gNB.h
+++ b/openair1/PHY/defs_gNB.h
@@ -122,8 +122,6 @@ typedef struct {
 
 typedef struct {
   uint8_t active;
-  int frame;
-  int slot;
   nfapi_nr_dl_tti_csi_rs_pdu csirs_pdu;
 } NR_gNB_CSIRS_t;
 
@@ -766,7 +764,6 @@ typedef struct PHY_VARS_gNB_s {
   NR_gNB_PUSCH       *pusch_vars[NUMBER_OF_NR_ULSCH_MAX];
   NR_gNB_PUCCH_t     *pucch[NUMBER_OF_NR_PUCCH_MAX];
   NR_gNB_PDCCH_t     pdcch_pdu[NUMBER_OF_NR_PDCCH_MAX];
-  NR_gNB_CSIRS_t     csirs_pdu[NUMBER_OF_NR_CSIRS_MAX];
   NR_gNB_UL_PDCCH_t  ul_pdcch_pdu[NUMBER_OF_NR_PDCCH_MAX];
   NR_gNB_DLSCH_t     *dlsch[NUMBER_OF_NR_DLSCH_MAX][2];    // Nusers times two spatial streams
   NR_gNB_ULSCH_t     *ulsch[NUMBER_OF_NR_ULSCH_MAX][2];  // [Nusers times][2 codewords] 
@@ -940,7 +937,12 @@ typedef struct processingData_L1 {
   int slot_tx;
   openair0_timestamp timestamp_tx;
   PHY_VARS_gNB *gNB;
-};
+} processingData_L1_t;
+
+typedef enum {
+  FILLED,
+  NOT_FILLED
+} msgStatus_t;
 
 typedef struct processingData_L1tx {
   int frame_rx;
@@ -951,10 +953,12 @@ typedef struct processingData_L1tx {
   PHY_VARS_gNB *gNB;
   nfapi_nr_dl_tti_pdcch_pdu pdcch_pdu;
   nfapi_nr_ul_dci_request_pdus_t ul_pdcch_pdu;
+  NR_gNB_CSIRS_t csirs_pdu[NUMBER_OF_NR_CSIRS_MAX];
   NR_gNB_DLSCH_t *dlsch[NUMBER_OF_NR_DLSCH_MAX][2];
   NR_gNB_SSB_t ssb[64];
   uint16_t num_pdsch_slot;
   time_stats_t phy_proc_tx;
+  msgStatus_t status;
 } processingData_L1tx_t;
 
 #endif
diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c
index 4457cfe642..e06d66ed02 100644
--- a/openair1/SCHED_NR/fapi_nr_l1.c
+++ b/openair1/SCHED_NR/fapi_nr_l1.c
@@ -100,45 +100,16 @@ void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx,int frame,int slot,
 }*/
 
 
-void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB,
-			       int frame, int slot,
-			       nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu) {
-
-  LOG_D(PHY,"Frame %d, Slot %d: DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, pdcch_pdu->pdcch_pdu_rel15.numDlDci);
-
-  // copy dci configuration into gNB structure
-  //  gNB->pdcch_pdu = pdcch_pdu;
-
-  nr_fill_dci(gNB,frame,slot,pdcch_pdu);
-
-}
-
-
-void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB,
-			       int frame, int slot,
-			       nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu) {
-
-  LOG_D(PHY,"Frame %d, Slot %d: UL DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci);
-
-  // copy dci configuration into gNB structure
-  //  gNB->ul_dci_pdu = ul_dci_request_pdu;
-
-  nr_fill_ul_dci(gNB,frame,slot,ul_dci_request_pdu);
-
-}
-
-void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB,
-			       int frame, int slot,
+void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx,
+             int frame,int slot,
 			       nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu) {
 
   int found = 0;
 
   for (int id=0; id<NUMBER_OF_NR_CSIRS_MAX; id++) {
-    NR_gNB_CSIRS_t *csirs = &gNB->csirs_pdu[id];
+    NR_gNB_CSIRS_t *csirs = &msgTx->csirs_pdu[id];
     if (csirs->active == 0) {
       LOG_D(PHY,"Frame %d Slot %d CSI_RS with ID %d is now active\n",frame,slot,id);
-      csirs->frame = frame;
-      csirs->slot = slot;
       csirs->active = 1;
       memcpy((void*)&csirs->csirs_pdu, (void*)csirs_pdu, sizeof(nfapi_nr_dl_tti_csi_rs_pdu));
       found = 1;
@@ -217,8 +188,8 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
       break;
       case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE:
         LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot);
-        handle_nfapi_nr_csirs_pdu(gNB,
-				  frame, slot,
+        handle_nfapi_nr_csirs_pdu(msgTx,
+          int frame,int slot,
 				  &dl_tti_pdu->csi_rs_pdu);
       break;
       case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE:
@@ -241,6 +212,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
   if(NFAPI_MODE != NFAPI_MODE_VNF)
     msgTx->ul_pdcch_pdu = UL_dci_req->ul_dci_pdu_list[number_ul_dci_pdu-1]; // copy the last pdu
 
+  msgTx->status = FILLED;
   pushNotifiedFIFO(gNB->resp_L1_tx,res);
 
   if(NFAPI_MODE != NFAPI_MODE_VNF)
diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c
index 9be6780597..c817efcd02 100644
--- a/openair1/SCHED_NR/phy_frame_config_nr.c
+++ b/openair1/SCHED_NR/phy_frame_config_nr.c
@@ -30,6 +30,7 @@
 ************************************************************************/
 
 #include "PHY/defs_nr_common.h"
+#include "PHY/defs_gNB.h"
 #include "PHY/defs_nr_UE.h"
 #include "SCHED_NR/phy_frame_config_nr.h"
 
@@ -308,6 +309,21 @@ int set_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms) {
 *
 *********************************************************************/
 
+int get_next_downlink_slot(PHY_VARS_gNB *gNB, nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot) {
+
+  int slot = nr_slot;
+  int frame = nr_frame;
+  int slots_per_frame = gNB->frame_parms.slots_per_frame;
+  while (true) {
+    slot++;
+    frame = (slot/slots_per_frame) ? frame++ : frame;
+    slot %= slots_per_frame;
+    int slot_type = nr_slot_select(cfg, frame, slot);
+    if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT) return slot;
+    AssertFatal(frame < nr_frame+2, "Something went worng. This shouldn't happen\n");
+  }
+}
+
 int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot) {
   /* for FFD all slot can be considered as an uplink */
   int mu = cfg->ssb_config.scs_common.value,check_slot=0;
diff --git a/openair1/SCHED_NR/phy_frame_config_nr.h b/openair1/SCHED_NR/phy_frame_config_nr.h
index 434dc41d1f..aba26283ed 100644
--- a/openair1/SCHED_NR/phy_frame_config_nr.h
+++ b/openair1/SCHED_NR/phy_frame_config_nr.h
@@ -92,5 +92,7 @@ void free_tdd_configuration_nr(NR_DL_FRAME_PARMS *frame_parms);
 
 void free_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms);
 
+int get_next_downlink_slot(PHY_VARS_gNB *gNB, nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot);
+
 #endif  /* PHY_FRAME_CONFIG_NR_H */
 
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index 185521d5df..22d97be0c3 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -129,7 +129,7 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
                            int slot,
                            int do_meas) {
   int aa;
-  PHY_VARS_gNB *gNB = msgTx->gNB,
+  PHY_VARS_gNB *gNB = msgTx->gNB;
   NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
   nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
   int offset = gNB->CC_id;
@@ -140,7 +140,7 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,1);
 
-  if (do_meas==1) start_meas(gNB->phy_proc_tx);
+  if (do_meas==1) start_meas(&msgTx->phy_proc_tx);
 
   // clear the transmit data array and beam index for the current slot
   for (aa=0; aa<cfg->carrier_config.num_tx_ant.value; aa++) {
@@ -159,24 +159,21 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
   }
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0);
 
-  LOG_D(PHY,"[gNB %d] Frame %d slot %d, pdcch_pdu_id %d, ul_pdcch_pdu_id %d\n",
-	gNB->Mod_id,frame,slot,pdcch_pdu_id,ul_pdcch_pdu_id);
+  int num_dl_dci = msgTx->pdcch_pdu.pdcch_pdu_rel15.numDlDci;
+  int num_ul_dci = msgTx->ul_pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci;
 
-  int num_ul_dci = msgTx->ul_pdcch_pdu.pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci;
-  int num_dl_dci = msgTx->pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci;
-
-  if (pdcch_pdu_id >= 0 || ul_pdcch_pdu_id >= 0) {
+  if (num_dl_dci > 0 || num_ul_dci > 0) {
     LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n",
 	  gNB->Mod_id, frame, slot, num_dl_dci, num_ul_dci);
   
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,1);
 
     nr_generate_dci_top(gNB,
-			num_dl_dci > 0 ? &msgTx->pdcch_pdu.pdcch_pdu : NULL,
-			num_ul_dci > 0 ? &msgTx->ul_pdcch_pdu.pdcch_pdu.pdcch_pdu : NULL,
+			num_dl_dci > 0 ? &msgTx->pdcch_pdu : NULL,
+			num_ul_dci > 0 ? &msgTx->ul_pdcch_pdu.pdcch_pdu : NULL,
 			gNB->nr_gold_pdcch_dmrs[slot],
 			&gNB->common_vars.txdataF[0][txdataF_offset],
-			AMP, fp);
+			AMP, &fp);
 
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,0);
   }
@@ -187,10 +184,8 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
 
   for (int i=0;i<NUMBER_OF_NR_CSIRS_MAX;i++){
-    NR_gNB_CSIRS_t *csirs = &gNB->csirs_pdu[i];
-    if ((csirs->active == 1) &&
-        (csirs->frame == frame) &&
-        (csirs->slot == slot) ) {
+    NR_gNB_CSIRS_t *csirs = &msgTx->csirs_pdu[i];
+    if ((csirs->active == 1)) {
       LOG_D(PHY, "CSI-RS generation started in frame %d.%d\n",frame,slot);
       nfapi_nr_dl_tti_csi_rs_pdu_rel15_t csi_params = csirs->csirs_pdu.csi_rs_pdu_rel15;
       nr_generate_csi_rs(gNB, AMP, csi_params, gNB->gNB_config.cell_config.phy_cell_id.value, slot);
@@ -198,7 +193,7 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
     }
   }
 
-  if (do_meas==1) stop_meas(gNB->phy_proc_tx);
+  if (do_meas==1) stop_meas(&msgTx->phy_proc_tx);
 
   if ((frame&127) == 0) dump_pdsch_stats(gNB);
 
diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h
index 5e31c08d38..d7e0332b85 100644
--- a/openair1/SCHED_NR/sched_nr.h
+++ b/openair1/SCHED_NR/sched_nr.h
@@ -36,7 +36,7 @@
 
 void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx);
 void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_scf_t *cfg, NR_DL_FRAME_PARMS *fp);
-void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, int frame_tx, int slot_tx, int do_meas);
+void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, int frame_tx, int slot_tx, int do_meas);
 void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx);
 int  phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx);
 void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot);
-- 
2.26.2