From 8c1f9c9e75b8900f4dfa448a5c341172156726b9 Mon Sep 17 00:00:00 2001
From: Raymond Knopp <raymond.knopp@eurecom.fr>
Date: Mon, 6 May 2019 16:04:04 +0200
Subject: [PATCH] modifications to synchronization between RU_TX and L1_TX
 (timed cond wait to drop slots)

tested on both 40 and 80 MHz channels
---
 openair1/PHY/defs_common.h    | 29 +++++++++++++++++++++++++++++
 targets/RT/USER/gNB_usrp.gtkw | 25 +++++++++++++++----------
 targets/RT/USER/nr-gnb.c      | 34 ++++++++++++++++++++++------------
 targets/RT/USER/nr-ru.c       |  4 +++-
 4 files changed, 69 insertions(+), 23 deletions(-)

diff --git a/openair1/PHY/defs_common.h b/openair1/PHY/defs_common.h
index f479c30b8c..c035b75fea 100644
--- a/openair1/PHY/defs_common.h
+++ b/openair1/PHY/defs_common.h
@@ -1011,6 +1011,35 @@ static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,
   return(0);
 }
 
+static inline int timedwait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name,uint32_t time_ns) {
+  int rc;
+  int waitret=0;
+  if ((rc = pthread_mutex_lock(mutex)) != 0) {
+    LOG_E(PHY, "[SCHED][eNB] wait_on_condition(): error locking mutex for %s (%d %s, %p)\n",
+        name, rc, strerror(rc), (void *)mutex);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+
+  struct timespec now,abstime;
+
+  while (*instance_cnt < 0) {
+    clock_gettime(CLOCK_REALTIME,&now);
+    // most of the time the thread is waiting here
+    // proc->instance_cnt_rxtx is -1
+    abstime.tv_sec=now.tv_sec;
+    abstime.tv_nsec = now.tv_nsec + time_ns;
+    if ((waitret = pthread_cond_timedwait(cond,mutex,&abstime))==ETIMEDOUT) break; // this unlocks mutex_rxtx while waiting and then locks it again
+    
+  }
+
+  if (pthread_mutex_unlock(mutex) != 0) {
+    LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  return(waitret);
+}
 static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
   int rc;
   if ((rc = pthread_mutex_lock(mutex)) != 0) {
diff --git a/targets/RT/USER/gNB_usrp.gtkw b/targets/RT/USER/gNB_usrp.gtkw
index 74e04e6a73..818cff3548 100644
--- a/targets/RT/USER/gNB_usrp.gtkw
+++ b/targets/RT/USER/gNB_usrp.gtkw
@@ -1,19 +1,19 @@
 [*]
 [*] GTKWave Analyzer v3.3.61 (w)1999-2014 BSI
-[*] Wed May  1 00:14:54 2019
+[*] Mon May  6 11:32:36 2019
 [*]
-[dumpfile] "/tmp/openair_dump_eNB.vcd"
-[dumpfile_mtime] "Wed May  1 00:10:57 2019"
-[dumpfile_size] 22152850
+[dumpfile] "/tmp/openair_dump_gNB40.vcd"
+[dumpfile_mtime] "Mon May  6 11:32:05 2019"
+[dumpfile_size] 803075
 [savefile] "/home/caracal/raymond/openairinterface5g/targets/RT/USER/gNB_usrp.gtkw"
-[timestart] 11537525000
-[size] 1859 841
+[timestart] 10835824000
+[size] 1920 859
 [pos] -1 -1
-*-19.848083 11540069031 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+*-19.848083 10838512202 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
 [sst_width] 386
 [signals_width] 344
 [sst_expanded] 1
-[sst_vpaned_height] 421
+[sst_vpaned_height] 197
 @28
 functions.trx_read
 functions.trx_write
@@ -30,8 +30,6 @@ variables.tti_number_TX0_RU[63:0]
 @28
 functions.mac_schedule_dlsch
 functions.macxface_eNB_dlsch_ulsch_scheduler
-functions.macxface_ue_scheduler
-functions.phy_eNB_ofdm_mod_l
 @24
 variables.frame_number_RX0_gNB[63:0]
 variables.slot_number_RX0_gNB[63:0]
@@ -46,6 +44,13 @@ variables.frame_number_TX1_gNB[63:0]
 variables.slot_number_TX1_gNB[63:0]
 @28
 functions.gNB_thread_rxtx1
+functions.phy_enb_pdcch_tx
+functions.phy_eNB_dlsch_encoding
+functions.phy_eNB_dlsch_encoding_w
+functions.generate_dlsch
+@421
+variables.frame_number_RX0_UE[63:0]
+@28
 functions.phy_procedures_ru_feprx0
 functions.phy_procedures_ru_feprx1
 functions.phy_procedures_ru_feptx_ofdm0
diff --git a/targets/RT/USER/nr-gnb.c b/targets/RT/USER/nr-gnb.c
index 6c30375d61..ecd5d035f7 100644
--- a/targets/RT/USER/nr-gnb.c
+++ b/targets/RT/USER/nr-gnb.c
@@ -248,7 +248,8 @@ static void* gNB_L1_thread_tx(void* param) {
   
   while (!oai_exit) {
     
-    if (wait_on_condition(&L1_proc_tx->mutex,&L1_proc_tx->cond,&L1_proc_tx->instance_cnt,thread_name)<0) break;
+    while (L1_proc_tx->instance_cnt==-1)
+       if (wait_on_condition(&L1_proc_tx->mutex,&L1_proc_tx->cond,&L1_proc_tx->instance_cnt,thread_name)<0) break;
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 1 );
     if (oai_exit) break;    
     // *****************************************
@@ -273,8 +274,8 @@ static void* gNB_L1_thread_tx(void* param) {
       exit_fun( "ERROR pthread_cond_signal" );
     }
     pthread_mutex_unlock( &L1_proc_tx->mutex );
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 );
     wakeup_txfh(gNB,L1_proc_tx,frame_tx,slot_tx,timestamp_tx);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 );
   }
 
   return 0;
@@ -398,22 +399,31 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot
   RU_t *ru;
   RU_proc_t *ru_proc;
 
-
+  int waitret;
   struct timespec wait;
   wait.tv_sec=0;
   wait.tv_nsec=5000000L;
+ 
 
-  if(wait_on_condition(&proc->mutex_RUs_tx,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")<0) {
-    LOG_E(PHY,"Frame %d, subframe %d: TX FH not ready\n", proc->frame_tx, proc->slot_tx);
-    return(-1);
-  }
+  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
+
+// note this  should depend on the numerology used by the TX L1 thread, set here for 500us slot time
+  waitret=timedwait_on_condition(&proc->mutex_RUs_tx,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh",500000); 
 
-  pthread_mutex_lock(&gNB->proc.mutex_RU_tx);
 
-  gNB->proc.RU_mask_tx = 0;
-  pthread_mutex_unlock(&gNB->proc.mutex_RU_tx);
   if (release_thread(&proc->mutex_RUs_tx,&proc->instance_cnt_RUs,"wakeup_txfh")<0) return(-1);
 
+  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
+ 
+  if (waitret == ETIMEDOUT) {
+     LOG_W(PHY,"Dropping TX slot because FH is blocked more than 2 slot times (1000us)\n");
+
+     pthread_mutex_lock(&gNB->proc.mutex_RU_tx);
+     gNB->proc.RU_mask_tx = 0;
+     pthread_mutex_unlock(&gNB->proc.mutex_RU_tx);
+
+     return(-1);
+  } 
   for(int i=0; i<gNB->num_RU; i++)
   {
     ru      = gNB->RU_list[i];
@@ -523,7 +533,7 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
 
   /* accept some delay in processing - up to 5ms */
   for (i = 0; i < fp->slots_per_frame && L1_proc->instance_cnt == 0; i++) {
-    LOG_W( PHY,"[gNB] SFN.SL %d.%d, gNB RXn-TXnp4 thread busy!! (i %d, cnt %i)\n", L1_proc->frame_tx, L1_proc->slot_tx, i,L1_proc->instance_cnt);
+    LOG_W( PHY,"[gNB] SFN.SL %d.%d, gNB L1 thread busy!! (i %d, cnt %i)\n", L1_proc->frame_tx, L1_proc->slot_tx, i,L1_proc->instance_cnt);
     usleep(100);
   }
   if (L1_proc->instance_cnt == 0) {
@@ -534,7 +544,7 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
   // wake up TX for subframe n+sl_ahead
   // lock the TX mutex and make sure the thread is ready
   if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) {
-    LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB RXTX thread %d (IC %d)\n", L1_proc->slot_rx&1,L1_proc->instance_cnt );
+    LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB L1 thread %d (IC %d)\n", L1_proc->slot_rx&1,L1_proc->instance_cnt );
     exit_fun( "error locking mutex" );
     return(-1);
   }
diff --git a/targets/RT/USER/nr-ru.c b/targets/RT/USER/nr-ru.c
index ad45218861..058ac8748c 100644
--- a/targets/RT/USER/nr-ru.c
+++ b/targets/RT/USER/nr-ru.c
@@ -791,7 +791,7 @@ void tx_rf(RU_t *ru) {
 				      txp,
 				      siglen+sf_extension,
 				      ru->nb_tx,
-				      flags);
+				      4);//flags);
     
     LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx,
 	  (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->tti_tx);
@@ -1370,6 +1370,8 @@ static void* ru_thread_tx( void* param ) {
 
         pthread_mutex_lock(&L1_proc->mutex_RUs_tx);
         L1_proc->instance_cnt_RUs = 0;
+        VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs);
+
         // the thread can now be woken up
         if (pthread_cond_signal(&L1_proc->cond_RUs) != 0) {
           LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB L1 TX thread\n");
-- 
2.26.2