Merge remote-tracking branch 'origin/ru_rau_enhancement_L1_renaming' into develop_integration_2019_w25

This commit is contained in:
Raphael Defosseux
2019-06-18 13:40:42 +02:00
234 changed files with 4738 additions and 592547 deletions
+165 -139
View File
@@ -29,6 +29,18 @@
* \note
* \warning
*/
/*! \function wakeup_txfh
* \brief Implementation of creating multiple RU threads for beamforming emulation
* \author TH Wang(Judy), TY Hsu, SY Yeh(fdragon)
* \date 2018
* \version 0.1
* \company Eurecom and ISIP@NCTU
* \email: Tsu-Han.Wang@eurecom.fr,tyhsu@cs.nctu.edu.tw,fdragon.cs96g@g2.nctu.edu.tw
* \note
* \warning
*/
#define _GNU_SOURCE
#include <pthread.h>
@@ -132,8 +144,8 @@ extern double cpuf;
void init_eNB(int,int);
void stop_eNB(int nb_inst);
int wakeup_tx(PHY_VARS_eNB *eNB);
int wakeup_txfh(L1_rxtx_proc_t *proc,PHY_VARS_eNB *eNB);
int wakeup_tx(PHY_VARS_eNB *eNB ,int frame_rx,int subframe_rx,int frame_tx,int subframe_tx,uint64_t timestamp_tx);
int wakeup_txfh(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc,int frame_tx,int subframe_tx,uint64_t timestamp_tx);
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
@@ -148,7 +160,9 @@ extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name) {
int ret;
start_meas(&softmodem_stats_rxtx_sf);
//L1_rxtx_proc_t *L1_proc_tx = &eNB->proc.L1_proc_tx;
// *******************************************************************
#if defined(PRE_SCD_THREAD)
@@ -224,10 +238,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name
memcpy(&pre_scd_eNB_UE_stats,&RC.mac[0]->UE_list.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX);
memcpy(&pre_scd_activeUE, &RC.mac[0]->UE_list.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX);
if (pthread_mutex_lock(&ru->proc.mutex_pre_scd)!= 0) {
LOG_E( PHY, "[eNB] error locking proc mutex for eNB pre scd\n");
exit_fun("error locking mutex_time");
}
AssertFatal((ret= pthread_mutex_lock(&ru->proc.mutex_pre_scd))==0,"[eNB] error locking proc mutex for eNB pre scd, return %d\n",ret);
ru->proc.instance_pre_scd++;
@@ -241,22 +252,22 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name
proc->frame_rx,proc->subframe_rx,ru->proc.instance_pre_scd );
}
if (pthread_mutex_unlock(&ru->proc.mutex_pre_scd)!= 0) {
LOG_E( PHY, "[eNB] error unlocking mutex_pre_scd mutex for eNB pre scd\n");
exit_fun("error unlocking mutex_pre_scd");
}
AssertFatal((ret= pthread_mutex_unlock(&ru->proc.mutex_pre_scd))==0,"[eNB] error unlocking proc mutex for eNB pre scd, return %d\n",ret);
}
#endif
pthread_mutex_lock(&eNB->UL_INFO_mutex);
AssertFatal((ret= pthread_mutex_lock(&eNB->UL_INFO_mutex))==0,"error locking UL_INFO_mutex, return %d\n",ret);
eNB->UL_INFO.frame = proc->frame_rx;
eNB->UL_INFO.subframe = proc->subframe_rx;
eNB->UL_INFO.module_id = eNB->Mod_id;
eNB->UL_INFO.CC_id = eNB->CC_id;
eNB->if_inst->UL_indication(&eNB->UL_INFO);
pthread_mutex_unlock(&eNB->UL_INFO_mutex);
AssertFatal((ret= pthread_mutex_unlock(&eNB->UL_INFO_mutex))==0,"error unlocking UL_INFO_mutex, return %d\n",ret);
/* this conflict resolution may be totally wrong, to be tested */
/* CONFLICT RESOLUTION: BEGIN */
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER, 0 );
if(oai_exit) return(-1);
@@ -271,6 +282,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name
//if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) return(-1);
/* CONFLICT RESOLUTION: END */
stop_meas( &softmodem_stats_rxtx_sf );
LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, proc->frame_rx, proc->subframe_rx, proc->frame_tx, proc->subframe_tx);
LOG_D(PHY, "rxtx:%lld nfapi:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ",
softmodem_stats_rxtx_sf.p_time, nfapi_meas.p_time,
@@ -279,6 +291,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name
TICK_TO_US(eNB->rx_prach),
TICK_TO_US(eNB->ofdm_mod_stats)
);
LOG_D(PHY,
"dlsch[enc:%lld mod:%lld scr:%lld rm:%lld t:%lld i:%lld] rx_dft:%lld ",
TICK_TO_US(eNB->dlsch_encoding_stats),
@@ -319,14 +332,17 @@ static void *L1_thread_tx(void *param) {
char thread_name[100];
sprintf(thread_name,"TXnp4_%d\n",&eNB->proc.L1_proc == proc ? 0 : 1);
thread_top_init(thread_name,1,470000,500000,500000);
int ret;
//wait_sync("tx_thread");
while (!oai_exit) {
LOG_D(PHY,"Waiting for TX (IC %d)\n",proc->instance_cnt);
if (wait_on_condition(&proc->mutex,&proc->cond,&proc->instance_cnt,thread_name)<0) break;
if (oai_exit) break;
LOG_D(PHY,"L1_thread_tx: Running for %d.%d\n",proc->frame_tx,proc->subframe_tx);
// *****************************************
// TX processing for subframe n+4
// run PHY TX procedures the one after the other for all CCs to avoid race conditions
@@ -336,18 +352,27 @@ static void *L1_thread_tx(void *param) {
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX1_ENB,proc->subframe_rx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_ENB,proc->frame_tx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_ENB,proc->frame_rx);
LOG_D(PHY,"L1 TX processing %d.%d\n",proc->frame_tx,proc->subframe_tx);
phy_procedures_eNB_TX(eNB, proc, 1);
pthread_mutex_lock( &proc->mutex );
AssertFatal((ret= pthread_mutex_lock( &proc->mutex ))==0,"error locking L1_proc_tx mutex, return %d\n",ret);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,proc->instance_cnt);
int subframe_tx = proc->subframe_tx;
int frame_tx = proc->frame_tx;
uint64_t timestamp_tx = proc->timestamp_tx;
proc->instance_cnt = -1;
LOG_D(PHY,"L1 TX signaling done for %d.%d\n",proc->frame_tx,proc->subframe_tx);
// the thread can now be woken up
LOG_D(PHY,"L1_thread_tx: signaling completion in %d.%d\n",proc->frame_tx,proc->subframe_tx);
if (pthread_cond_signal(&proc->cond) != 0) {
LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
exit_fun( "ERROR pthread_cond_signal" );
}
pthread_mutex_unlock( &proc->mutex );
wakeup_txfh(proc,eNB);
AssertFatal((ret= pthread_mutex_unlock( &proc->mutex ))==0,"error unlocking L1_proc_tx mutex, return %d\n",ret);
wakeup_txfh(eNB,proc,frame_tx,subframe_tx,timestamp_tx);
}
return 0;
@@ -361,9 +386,7 @@ static void *L1_thread_tx(void *param) {
static void *L1_thread( void *param ) {
static int eNB_thread_rxtx_status;
//L1_proc_t *eNB_proc = (L1_proc_t*)param;
L1_rxtx_proc_t *proc;
// Working
if(NFAPI_MODE==NFAPI_MODE_VNF) {
proc = (L1_rxtx_proc_t *)param;
@@ -387,8 +410,10 @@ static void *L1_thread( void *param ) {
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
LOG_D(PHY,"L1RX waiting for RU RX\n");
if (wait_on_condition(&proc->mutex,&proc->cond,&proc->instance_cnt,thread_name)<0) break;
LOG_D(PHY,"L1RX starting in %d.%d\n",proc->frame_rx,proc->subframe_rx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_ENB_THREAD_RXTX,sched_getcpu());
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 );
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB,proc->subframe_tx);
@@ -396,20 +421,26 @@ static void *L1_thread( void *param ) {
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB,proc->frame_tx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_ENB,proc->frame_rx);
if (oai_exit) break;
if (eNB->CC_id==0) {
if (rxtx(eNB,proc,thread_name) < 0) break;
}
LOG_D(PHY,"L1 RX %d.%d done\n",proc->frame_rx,proc->subframe_rx);
if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) phy_procedures_eNB_TX(eNB, proc, 1);
if (NFAPI_MODE!=NFAPI_MODE_VNF) {
if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(eNB,proc->frame_rx,proc->subframe_rx,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx);
else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) wakeup_txfh(eNB,proc,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx);
}
if (release_thread(&proc->mutex,&proc->instance_cnt,thread_name)<0) break;
if (NFAPI_MODE!=NFAPI_MODE_VNF) {
if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(eNB);
else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) wakeup_txfh(proc,eNB);
}
} // while !oai_exit
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
@@ -442,90 +473,104 @@ void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string,RU_t
}
}
int wakeup_txfh(L1_rxtx_proc_t *proc,PHY_VARS_eNB *eNB) {
int wakeup_txfh(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc,int frame_tx,int subframe_tx,uint64_t timestamp_tx) {
RU_t *ru;
RU_proc_t *ru_proc;
struct timespec wait;
wait.tv_sec=0;
wait.tv_nsec=5000000L;
LTE_DL_FRAME_PARMS *fp;
int waitret,ret;
if(wait_on_condition(&proc->mutex_RUs,&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->subframe_tx);
return(-1);
}
LOG_D(PHY,"L1 TX Waking up TX FH %d.%d (IC RU TX %d)\n",frame_tx,subframe_tx,proc->instance_cnt_RUs);
pthread_mutex_lock(&eNB->proc.mutex_RU_tx);
eNB->proc.RU_mask_tx = 0;
pthread_mutex_unlock(&eNB->proc.mutex_RU_tx);
// grab the information for the RU due to the following wait
if (release_thread(&proc->mutex_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")<0) return(-1);
waitret=timedwait_on_condition(&proc->mutex_RUs,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh",1000000);
for(int i=0; i<eNB->num_RU; i++) {
ru = eNB->RU_list[i];
AssertFatal(release_thread(&proc->mutex_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")==0, "error releaseing eNB lock on RUs\n");
if (waitret == ETIMEDOUT) {
LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 subframe times (1ms)\n",frame_tx,subframe_tx);
AssertFatal((ret=pthread_mutex_lock(&eNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
eNB->proc.RU_mask_tx = 0;
AssertFatal((ret=pthread_mutex_unlock(&eNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs))==0,"mutex_lock returns %d\n",ret);
proc->instance_cnt_RUs = 0;
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs))==0,"mutex_unlock returns %d\n",ret);
return(-1);
}
for(int ru_id=0; ru_id<eNB->num_RU; ru_id++){
ru = eNB->RU_list[ru_id];
ru_proc = &ru->proc;
fp = &ru->frame_parms;
if (((fp->frame_type == TDD) && (subframe_select(fp,proc->subframe_tx)==SF_UL))||
(eNB->RU_list[ru_id]->state == RU_SYNC)||
(eNB->RU_list[ru_id]->wait_cnt>0)){
AssertFatal((pthread_mutex_lock(&proc->mutex_RUs))==0, "mutex_lock returns %d\n",ret);
proc->instance_cnt_RUs = 0;
AssertFatal((pthread_mutex_unlock(&proc->mutex_RUs))==0, "mutex_unlock returns %d\n",ret);
continue;//hacking only works when all RU_tx works on the same subframe #TODO: adding mask stuff
}
AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_eNBs))==0,"ERROR pthread_mutex_lock failed on mutex_eNBs L1_thread_tx with ret=%d\n",ret);
if (ru_proc->instance_cnt_eNBs == 0) {
LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->subframe_tx, proc->frame_rx, proc->subframe_rx);
return(-1);
}
if (pthread_mutex_timedlock(&ru_proc->mutex_eNBs,&wait) != 0) {
LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX1 thread %d (IC %d)\n", ru_proc->subframe_rx&1,ru_proc->instance_cnt_eNBs );
exit_fun( "error locking mutex_eNB" );
AssertFatal((ret=pthread_mutex_lock(&eNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
eNB->proc.RU_mask_tx = 0;
AssertFatal((ret=pthread_mutex_unlock(&eNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
AssertFatal((ret=pthread_mutex_unlock( &ru_proc->mutex_eNBs ))==0,"mutex_unlock return %d\n",ret);
return(-1);
}
ru_proc->instance_cnt_eNBs = 0;
ru_proc->timestamp_tx = proc->timestamp_tx;
ru_proc->subframe_tx = proc->subframe_tx;
ru_proc->frame_tx = proc->frame_tx;
ru_proc->timestamp_tx = timestamp_tx;
ru_proc->subframe_tx = subframe_tx;
ru_proc->frame_tx = frame_tx;
LOG_D(PHY,"L1 TX Waking up TX FH (2) %d.%d\n",frame_tx,subframe_tx);
// the thread can now be woken up
if (pthread_cond_signal(&ru_proc->cond_eNBs) != 0) {
LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
exit_fun( "ERROR pthread_cond_signal" );
return(-1);
}
pthread_mutex_unlock( &ru_proc->mutex_eNBs );
AssertFatal(pthread_cond_signal(&ru_proc->cond_eNBs) == 0,
"[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_eNBs))==0,"mutex_unlock returned %d\n",ret);
}
return(0);
}
int wakeup_tx(PHY_VARS_eNB *eNB) {
L1_proc_t *proc=&eNB->proc;
L1_rxtx_proc_t *L1_proc_tx = &proc->L1_proc_tx;
L1_rxtx_proc_t *L1_proc = &proc->L1_proc;
struct timespec wait;
wait.tv_sec=0;
wait.tv_nsec=5000000L;
int wakeup_tx(PHY_VARS_eNB *eNB, int frame_rx,int subframe_rx,int frame_tx,int subframe_tx,uint64_t timestamp_tx) {
if (pthread_mutex_timedlock(&L1_proc_tx->mutex,&wait) != 0) {
LOG_E(PHY, "[SCHED][eNB] ERROR locking mutex for eNB L1_thread_tx\n");
exit_fun("ERROR pthread_lock");
return(-1);
}
L1_rxtx_proc_t *L1_proc = &eNB->proc.L1_proc;
L1_rxtx_proc_t *L1_proc_tx = &eNB->proc.L1_proc_tx;
int ret;
LOG_D(PHY,"ENTERED wakeup_tx (IC %d)\n",L1_proc_tx->instance_cnt);
AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret);
LOG_D(PHY,"L1 RX %d.%d Waiting to wake up L1 TX %d.%d (IC L1TX %d)\n",L1_proc->frame_rx,L1_proc->subframe_rx,L1_proc->frame_tx,L1_proc->subframe_tx,L1_proc_tx->instance_cnt);
while(L1_proc_tx->instance_cnt == 0) {
pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex);
}
LOG_D(PHY,"L1 RX Got signal that TX %d.%d is done\n",L1_proc_tx->frame_tx,L1_proc_tx->subframe_tx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,L1_proc_tx->instance_cnt);
L1_proc_tx->instance_cnt = 0;
L1_proc_tx->subframe_rx = L1_proc->subframe_rx;
L1_proc_tx->frame_rx = L1_proc->frame_rx;
L1_proc_tx->subframe_tx = L1_proc->subframe_tx;
L1_proc_tx->frame_tx = L1_proc->frame_tx;
L1_proc_tx->timestamp_tx = L1_proc->timestamp_tx;
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,L1_proc_tx->instance_cnt);
L1_proc_tx->subframe_rx = subframe_rx;
L1_proc_tx->frame_rx = frame_rx;
L1_proc_tx->subframe_tx = subframe_tx;
L1_proc_tx->frame_tx = frame_tx;
L1_proc_tx->timestamp_tx = timestamp_tx;
// the thread can now be woken up
if (pthread_cond_signal(&L1_proc_tx->cond) != 0) {
LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
exit_fun( "ERROR pthread_cond_signal" );
return(-1);
}
LOG_D(PHY,"L1 RX Waking up L1 TX %d.%d\n",L1_proc->frame_tx,L1_proc->subframe_tx);
AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for eNB L1 thread tx\n");
pthread_mutex_unlock( &L1_proc_tx->mutex);
AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret);
return(0);
}
@@ -534,44 +579,20 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {
RU_proc_t *ru_proc=&ru->proc;
L1_rxtx_proc_t *L1_proc=&proc->L1_proc;
LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
int i;
struct timespec wait;
pthread_mutex_lock(&proc->mutex_RU);
int ret;
for (i=0; i<eNB->num_RU; i++) {
if (ru == eNB->RU_list[i]) {
if ((proc->RU_mask&(1<<i)) > 0)
LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
eNB->Mod_id,proc->frame_rx,proc->subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask);
LOG_D(PHY,"ENTERED wakeup_rxtx, %d.%d\n",ru_proc->frame_rx,ru_proc->subframe_rx);
proc->RU_mask |= (1<<i);
}
}
if (proc->RU_mask != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return
LOG_E(PHY,"Not all RUs have provided their info\n");
pthread_mutex_unlock(&proc->mutex_RU);
return(0);
} else { // all RUs have provided their information so continue on and wakeup eNB processing
proc->RU_mask = 0;
pthread_mutex_unlock(&proc->mutex_RU);
}
wait.tv_sec=0;
wait.tv_nsec=5000000L;
if (L1_proc->instance_cnt == 0) {
LOG_E(PHY,"Frame %d, subframe %d: RXTX0 thread busy, dropping\n",L1_proc->frame_rx,L1_proc->subframe_rx);
return(-1);
}
// wake up TX for subframe n+sf_ahead
// 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, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", L1_proc->subframe_rx&1,L1_proc->instance_cnt );
exit_fun( "error locking mutex_rxtx" );
return(-1);
AssertFatal((ret=pthread_mutex_lock(&L1_proc->mutex)) == 0,"mutex_lock returns %d\n", ret);
if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe
AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"mutex_unlock return %d\n",ret);
LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->subframe_rx);
return(0);
}
++L1_proc->instance_cnt;
// We have just received and processed the common part of a subframe, say n.
@@ -586,6 +607,13 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {
L1_proc->frame_tx = (L1_proc->subframe_rx > (9-sf_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
L1_proc->subframe_tx = (L1_proc->subframe_rx + sf_ahead)%10;
LOG_D(PHY,"wakeup_rxtx: L1_proc->subframe_rx %d, L1_proc->subframe_tx %d, RU %d\n",L1_proc->subframe_rx,L1_proc->subframe_tx,ru->idx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_RX_RU+ru->idx, L1_proc->frame_rx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_RX_RU+ru->idx, L1_proc->subframe_rx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->frame_tx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->subframe_tx);
// the thread can now be woken up
if (pthread_cond_signal(&L1_proc->cond) != 0) {
LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n");
@@ -593,18 +621,19 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {
return(-1);
}
pthread_mutex_unlock( &L1_proc->mutex);
AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"mutex_unlock return %d\n",ret);
return(0);
}
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
L1_proc_t *proc = &eNB->proc;
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
int i;
int i,ret;
if (ru!=NULL) {
pthread_mutex_lock(&proc->mutex_RU_PRACH);
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU_PRACH))==0,"mutex_lock return %d\n",ret);
for (i=0; i<eNB->num_RU; i++) {
if (ru == eNB->RU_list[i]) {
LOG_D(PHY,"frame %d, subframe %d: RU %d for eNB %d signals PRACH (mask %x, num_RU %d)\n",frame,subframe,i,eNB->Mod_id,proc->RU_mask_prach,eNB->num_RU);
@@ -618,11 +647,11 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
}
if (proc->RU_mask_prach != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return
pthread_mutex_unlock(&proc->mutex_RU_PRACH);
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU_PRACH))==0,"mutex_unlock return %d\n",ret);
return;
} else { // all RUs have provided their information so continue on and wakeup eNB processing
proc->RU_mask_prach = 0;
pthread_mutex_unlock(&proc->mutex_RU_PRACH);
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU_PRACH))==0,"mutex_unlock return %d\n",ret);
}
}
@@ -636,11 +665,7 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
}
// wake up thread for PRACH RX
if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach);
exit_fun( "error locking mutex_prach" );
return;
}
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_prach))==0,"[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach);
++proc->instance_cnt_prach;
// set timing for prach thread
@@ -654,7 +679,7 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
return;
}
pthread_mutex_unlock( &proc->mutex_prach );
AssertFatal((ret=pthread_mutex_unlock( &proc->mutex_prach))==0,"mutex_unlock return %d\n",ret);
}
}
@@ -662,10 +687,10 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
L1_proc_t *proc = &eNB->proc;
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
int i;
int i,ret;
if (ru!=NULL) {
pthread_mutex_lock(&proc->mutex_RU_PRACH_br);
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU_PRACH_br))==0,"mutex_lock return %d\n",ret);
for (i=0; i<eNB->num_RU; i++) {
if (ru == eNB->RU_list[i]) {
@@ -680,11 +705,11 @@ void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
}
if (proc->RU_mask_prach_br != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return
pthread_mutex_unlock(&proc->mutex_RU_PRACH_br);
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU_PRACH_br))==0,"mutex_unlock return %d\n",ret);
return;
} else { // all RUs have provided their information so continue on and wakeup eNB processing
proc->RU_mask_prach_br = 0;
pthread_mutex_unlock(&proc->mutex_RU_PRACH_br);
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU_PRACH_br))==0,"mutex_unlock return %d\n",ret);
}
}
@@ -698,11 +723,7 @@ void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
}
// wake up thread for PRACH RX
if (pthread_mutex_lock(&proc->mutex_prach_br) != 0) {
LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach_br);
exit_fun( "error locking mutex_prach" );
return;
}
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_prach_br))==0,"[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach_br);
++proc->instance_cnt_prach_br;
// set timing for prach thread
@@ -716,7 +737,7 @@ void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
return;
}
pthread_mutex_unlock( &proc->mutex_prach_br );
AssertFatal((ret=pthread_mutex_unlock( &proc->mutex_prach_br))==0,"mutex_unlock return %d\n",ret);
}
}
#endif
@@ -860,7 +881,7 @@ void init_eNB_proc(int inst) {
proc->first_rx =1;
proc->first_tx =1;
proc->RU_mask_tx = (1<<eNB->num_RU)-1;
proc->RU_mask =0;
memset((void*)proc->RU_mask,0,10*sizeof(proc->RU_mask[0]));
proc->RU_mask_prach =0;
pthread_mutex_init( &eNB->UL_INFO_mutex, NULL);
pthread_mutex_init( &L1_proc->mutex, NULL);
@@ -960,6 +981,7 @@ void kill_eNB_proc(int inst) {
PHY_VARS_eNB *eNB;
L1_proc_t *proc;
L1_rxtx_proc_t *L1_proc, *L1_proc_tx;
int ret;
for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
eNB=RC.eNB[inst][CC_id];
@@ -975,32 +997,32 @@ void kill_eNB_proc(int inst) {
LOG_I(PHY, "Killing TX CC_id %d inst %d\n", CC_id, inst );
if ((get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) && NFAPI_MODE!=NFAPI_MODE_VNF) {
pthread_mutex_lock(&L1_proc->mutex);
AssertFatal((ret=pthread_mutex_lock(&L1_proc->mutex))==0,"mutex_lock return %d\n",ret);
L1_proc->instance_cnt = 0;
pthread_cond_signal(&L1_proc->cond);
pthread_mutex_unlock(&L1_proc->mutex);
pthread_mutex_lock(&L1_proc_tx->mutex);
AssertFatal((ret=pthread_mutex_unlock(&L1_proc->mutex))==0,"mutex_unlock return %d\n",ret);
AssertFatal((ret=pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock return %d\n",ret);
L1_proc_tx->instance_cnt = 0;
pthread_cond_signal(&L1_proc_tx->cond);
pthread_mutex_unlock(&L1_proc_tx->mutex);
AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"muex_unlock return %d\n",ret);
}
pthread_mutex_lock(&proc->mutex_prach);
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_prach))==0,"mutex_lock return %d\n",ret);
proc->instance_cnt_prach = 0;
pthread_cond_signal( &proc->cond_prach );
pthread_mutex_unlock(&proc->mutex_prach);
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_prach))==0,"mutex_unlock return %d\n",ret);
pthread_cond_signal( &proc->cond_asynch_rxtx );
pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
LOG_D(PHY, "joining pthread_prach\n");
pthread_join( proc->pthread_prach, (void **)&status );
LOG_I(PHY, "Destroying prach mutex/cond\n");
pthread_mutex_destroy( &proc->mutex_prach );
pthread_mutex_destroy( &proc->mutex_prach);
pthread_cond_destroy( &proc->cond_prach );
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
proc->instance_cnt_prach_br = 0;
pthread_cond_signal( &proc->cond_prach_br );
pthread_join( proc->pthread_prach_br, (void **)&status );
pthread_mutex_destroy( &proc->mutex_prach_br );
pthread_mutex_destroy( &proc->mutex_prach_br);
pthread_cond_destroy( &proc->cond_prach_br );
#endif
LOG_I(PHY, "Destroying UL_INFO mutex\n");
@@ -1267,7 +1289,11 @@ void init_eNB(int single_thread_flag,int wait_for_sync) {
}
}
LOG_I(PHY,"[lte-softmodem.c] eNB structure allocated\n");
}
+1094 -1080
View File
File diff suppressed because it is too large Load Diff
+31 -37
View File
@@ -80,7 +80,7 @@ unsigned short config_frames[4] = {2,9,11,13};
//#include "PHY/TOOLS/time_meas.h"
#ifndef OPENAIR2
#include "UTIL/OTG/otg_vars.h"
#include "UTIL/OTG/otg_vars.h"
#endif
@@ -91,7 +91,6 @@ unsigned short config_frames[4] = {2,9,11,13};
#include "system.h"
#include "lte-softmodem.h"
#include "NB_IoT_interface.h"
@@ -151,7 +150,6 @@ char channels[128] = "0";
int rx_input_level_dBm;
int otg_enabled;
@@ -286,7 +284,6 @@ void exit_function(const char *file, const char *function, const int line, const
}
static void get_options(void) {
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
get_common_options();
@@ -622,7 +619,7 @@ int main( int argc, char **argv ) {
ctxt.subframe = 0;
pdcp_run(&ctxt);
}
/* start threads if only L1 or not a CU */
if (RC.nb_inst == 0 || !NODE_IS_CU(RC.rrc[0]->node_type)) {
// init UE_PF_PO and mutex lock
@@ -632,58 +629,56 @@ int main( int argc, char **argv ) {
pthread_cond_init(&sync_cond,NULL);
pthread_mutex_init(&sync_mutex, NULL);
rt_sleep_ns(10*100000000ULL);
if (NFAPI_MODE!=NFAPI_MONOLITHIC) {
LOG_I(ENB_APP,"NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
pthread_cond_init(&sync_cond,NULL);
pthread_mutex_init(&sync_mutex, NULL);
}
if (NFAPI_MODE==NFAPI_MODE_VNF) {// VNF
#if defined(PRE_SCD_THREAD)
init_ru_vnf(); // ru pointer is necessary for pre_scd.
#endif
wait_nfapi_init("main?");
}
LOG_I(ENB_APP,"START MAIN THREADS\n");
// start the main threads
number_of_cards = 1;
printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
if (RC.nb_L1_inst > 0) {
printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync);
init_eNB(get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync);
// for (inst=0;inst<RC.nb_L1_inst;inst++)
// for (CC_id=0;CC_id<RC.nb_L1_CC[inst];CC_id++) phy_init_lte_eNB(RC.eNB[inst][CC_id],0,0);
}
}
printf("wait_eNBs()\n");
wait_eNBs();
printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
// RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator.
// but RU thread deals with pre_scd and this is necessary in VNF and simulator.
// some initialization is necessary and init_ru_vnf do this.
if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) {
printf("Initializing RU threads\n");
init_RU(get_softmodem_params()->rf_config_file);
for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
RC.ru[ru_id]->rf_map.card=0;
RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset);
}
printf("wait_eNBs()\n");
wait_eNBs();
printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
// RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator.
// but RU thread deals with pre_scd and this is necessary in VNF and simulator.
// some initialization is necessary and init_ru_vnf do this.
if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) {
printf("Initializing RU threads\n");
init_RU(get_softmodem_params()->rf_config_file,get_softmodem_params()->clock_source,get_softmodem_params()->timing_source,get_softmodem_params()->send_dmrs_sync);
for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
RC.ru[ru_id]->rf_map.card=0;
RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset);
}
config_sync_var=0;
if (NFAPI_MODE==NFAPI_MODE_PNF) { // PNF
wait_nfapi_init("main?");
}
printf("wait RUs\n");
// CI -- Flushing the std outputs for the previous marker to show on the eNB / RRU log file
fflush(stdout);
@@ -711,7 +706,6 @@ int main( int argc, char **argv ) {
pthread_mutex_unlock(&sync_mutex);
config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
}
// wait for end of program
LOG_UI(ENB_APP,"TYPE <CTRL-C> TO TERMINATE\n");
// CI -- Flushing the std outputs for the previous marker to show on the eNB / DU / CU log file
@@ -738,8 +732,8 @@ int main( int argc, char **argv ) {
* threads have been stopped (they partially use the same memory) */
for (int inst = 0; inst < NB_eNB_INST; inst++) {
for (int cc_id = 0; cc_id < RC.nb_CC[inst]; cc_id++) {
free_transport(RC.eNB[inst][cc_id]);
phy_free_lte_eNB(RC.eNB[inst][cc_id]);
free_transport(RC.eNB[inst][cc_id]);
phy_free_lte_eNB(RC.eNB[inst][cc_id]);
}
}
@@ -757,17 +751,17 @@ int main( int argc, char **argv ) {
for(ru_id=0; ru_id<RC.nb_RU; ru_id++) {
if (RC.ru[ru_id]->rfdevice.trx_end_func) {
RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
}
if (RC.ru[ru_id]->ifdevice.trx_end_func) {
RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
}
}
}
terminate_opt();
logClean();
printf("Bye.\n");
+7 -1
View File
@@ -59,6 +59,8 @@
#define CONFIG_HLP_UELOOP "get softmodem (UE) to loop through memory instead of acquiring from HW\n"
#define CONFIG_HLP_PHYTST "test UE phy layer, mac disabled\n"
#define CONFIG_HLP_DMAMAP "sets flag for improved EXMIMO UE performance\n"
#define CONFIG_HLP_EXTS "tells hardware to use an external timing reference\n"
#define CONFIG_HLP_DMRSSYNC "tells RU to insert DMRS in subframe 1 slot 0"
#define CONFIG_HLP_CLK "tells hardware to use a clock reference (0:internal, 1:external, 2:gpsdo)\n"
#define CONFIG_HLP_USIM "use XOR autentication algo in case of test usim mode\n"
#define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n"
@@ -182,6 +184,8 @@
#define NUMEROLOGY softmodem_params.numerology
#define EMULATE_RF softmodem_params.emulate_rf
#define CLOCK_SOURCE softmodem_params.clock_source
#define TIMING_SOURCE softmodem_params.timing_source
#define SEND_DMRSSYNC softmodem_params.send_dmrs_sync
#define USIM_TEST softmodem_params.usim_test
#define CMDLINE_PARAMS_DESC { \
{"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&RF_CONFIG_FILE, defstrval:NULL, TYPE_STRING, sizeof(RF_CONFIG_FILE)}, \
@@ -258,7 +262,9 @@ typedef struct {
int numerology;
unsigned int start_msc;
uint32_t clock_source;
uint32_t timing_source;
int hw_timing_advance;
uint32_t send_dmrs_sync;
} softmodem_params_t;
#define IS_SOFTMODEM_NOS1 ( get_softmodem_optmask() & SOFTMODEM_NOS1_BIT)
@@ -302,7 +308,7 @@ extern void stop_eNB(int);
extern void kill_eNB_proc(int inst);
// In lte-ru.c
extern void init_RU(char *);
extern void init_RU(char*,clock_source_t clock_source,clock_source_t time_source,int send_dmrssync);
extern void stop_ru(RU_t *ru);
extern void init_ru_vnf(void);
extern void init_RU_proc(RU_t *ru);
+2 -2
View File
@@ -890,7 +890,7 @@ void ue_stub_rx_handler(unsigned int num_bytes, char *rx_buffer) {
switch (((UE_tport_header_t *)rx_buffer)->packet_type) {
case TTI_SYNC:
emulator_absSF = ((UE_tport_header_t *)rx_buffer)->absSF;
wakeup_thread(&UE->timer_mutex,&UE->timer_cond,&UE->instance_cnt_timer,"timer_thread");
wakeup_thread(&UE->timer_mutex,&UE->timer_cond,&UE->instance_cnt_timer,"timer_thread",100,1);
break;
case SLSCH:
@@ -1749,7 +1749,7 @@ void *UE_thread(void *arg) {
LOG_E(PHY,"Missed real time\n");
continue;
} else {
LOG_E(PHY,"System error\n");
LOG_E(PHY,"System error %s (%d)\n",strerror(errno),errno);
abort();
}
}
+5 -2
View File
@@ -117,7 +117,8 @@ uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75,
volatile int oai_exit = 0;
clock_source_t clock_source = internal;
clock_source_t clock_source = internal,time_source=internal;
unsigned int mmapped_dma=0;
@@ -324,10 +325,12 @@ static void get_options(void) {
int CC_id;
int tddflag;
char *loopfile=NULL;
int dumpframe;
int dumpframe=0;
int timingadv;
uint8_t nfapi_mode;
int simL1flag ;
set_default_frame_parms(frame_parms);
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
/* unknown parameters on command line will be checked in main
+19 -149
View File
@@ -1,161 +1,31 @@
[*]
[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
[*] Sat Aug 6 15:00:27 2016
[*] GTKWave Analyzer v3.3.61 (w)1999-2014 BSI
[*] Fri Aug 17 14:21:15 2018
[*]
[dumpfile] "/tmp/openair_dump_eNB.vcd"
[dumpfile_mtime] "Sat Aug 6 14:59:21 2016"
[dumpfile_size] 991809002
[savefile] "/home/fourmi/openairinterface5g/targets/RT/USER/rcc_if4.gtkw"
[timestart] 0
[size] 1301 716
[pos] 309 0
*-19.793451 7382528436 -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] 284
[dumpfile_mtime] "Fri Aug 17 11:03:54 2018"
[dumpfile_size] 15491138
[savefile] "/home/knopp/oai/openairinterface5g/targets/RT/USER/rcc_if4.gtkw"
[timestart] 293296100000
[size] 1650 600
[pos] -1 -1
*-25.000000 293330000000 -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] 351
[signals_width] 262
[sst_expanded] 1
[sst_vpaned_height] 294
@24
variables.trx_ts[63:0]
variables.trx_tst[63:0]
[sst_vpaned_height] 139
@29
functions.send_if4
@28
functions.recv_if4
functions.send_if4
functions.eNB_thread_rxtx0
@24
variables.frame_number_RX0_eNB[63:0]
variables.subframe_number_RX0_RU[63:0]
variables.subframe_number_RX0_eNB[63:0]
variables.frame_number_TX0_eNB[63:0]
variables.subframe_number_TX0_RU[63:0]
variables.subframe_number_TX0_eNB[63:0]
@28
functions.phy_procedures_eNb_tx0
functions.phy_procedures_eNb_rx_common0
functions.phy_procedures_eNb_rx_uespec0
functions.eNB_thread_rxtx1
@24
variables.frame_number_RX1_eNB[63:0]
variables.subframe_number_RX1_eNB[63:0]
variables.frame_number_TX1_eNB[63:0]
variables.subframe_number_TX1_eNB[63:0]
@29
functions.phy_procedures_eNb_tx1
@28
functions.phy_procedures_eNb_rx_common1
functions.phy_procedures_eNb_rx_uespec1
functions.phy_enb_sfgen
functions.phy_eNB_slot_fep
functions.phy_enb_prach_rx
@24
variables.dci_info[63:0]
variables.ue0_BO[63:0]
@420
variables.ue0_BSR[63:0]
variables.ue0_timing_advance[63:0]
@28
functions.macxface_initiate_ra_proc
functions.macxface_terminate_ra_proc
functions.phy_enb_ulsch_msg3
functions.macxface_SR_indication
@420
variables.ue0_SR_ENERGY[63:0]
variables.ue0_SR_THRES[63:0]
@28
functions.phy_enb_ulsch_decoding0
@24
variables.ue0_res0[63:0]
@420
variables.ue0_rssi0[63:0]
variables.ue0_MCS0[63:0]
variables.ue0_RB0[63:0]
@24
variables.ue0_ROUND0[63:0]
variables.ue0_SFN0[63:0]
@28
functions.phy_enb_ulsch_decoding1
@24
variables.ue0_res1[63:0]
@420
variables.ue0_rssi1[63:0]
variables.ue0_MCS1[63:0]
variables.ue0_RB1[63:0]
@24
variables.ue0_ROUND1[63:0]
variables.ue0_SFN1[63:0]
@28
functions.phy_enb_ulsch_decoding2
@24
variables.ue0_res2[63:0]
@420
variables.ue0_rssi2[63:0]
variables.ue0_MCS2[63:0]
variables.ue0_RB2[63:0]
@24
variables.ue0_ROUND2[63:0]
variables.ue0_SFN2[63:0]
@28
functions.phy_enb_ulsch_decoding3
@24
variables.ue0_res3[63:0]
@420
variables.ue0_rssi3[63:0]
variables.ue0_MCS3[63:0]
variables.ue0_RB3[63:0]
@24
variables.ue0_ROUND3[63:0]
variables.ue0_SFN3[63:0]
@28
functions.phy_enb_ulsch_decoding4
@420
variables.ue0_rssi4[63:0]
@24
variables.ue0_res4[63:0]
@420
variables.ue0_MCS4[63:0]
variables.ue0_RB4[63:0]
@24
variables.ue0_ROUND4[63:0]
variables.ue0_SFN4[63:0]
@28
functions.phy_enb_ulsch_decoding5
@24
variables.ue0_res5[63:0]
@420
variables.ue0_rssi5[63:0]
variables.ue0_MCS5[63:0]
variables.ue0_RB5[63:0]
@24
variables.ue0_ROUND5[63:0]
variables.ue0_SFN5[63:0]
@28
functions.phy_enb_ulsch_decoding6
@24
variables.ue0_res6[63:0]
@420
variables.ue0_rssi6[63:0]
variables.ue0_MCS6[63:0]
variables.ue0_RB6[63:0]
@24
variables.ue0_ROUND6[63:0]
variables.ue0_SFN6[63:0]
@28
functions.phy_enb_ulsch_decoding7
@24
variables.ue0_res7[63:0]
@420
variables.ue0_rssi7[63:0]
variables.ue0_MCS7[63:0]
variables.ue0_RB7[63:0]
@24
variables.ue0_ROUND7[63:0]
variables.ue0_SFN7[63:0]
@28
functions.phy_enb_prach_rx
functions.phy_eNB_dlsch_encoding
functions.phy_eNB_dlsch_modulation
functions.phy_eNB_dlsch_scrambling
functions.phy_enb_pdcch_tx
functions.phy_enb_rs_tx
functions.rrc_mac_config_req
functions.rlc_data_req
functions.udp_enb_task
variables.frame_number_TX0_RU[63:0]
variables.frame_number_TX0_eNB[63:0]
variables.frame_number_RX0_eNB[63:0]
variables.frame_number_RX0_RU[63:0]
[pattern_trace] 1
[pattern_trace] 0
+7 -5
View File
@@ -62,6 +62,9 @@ sim_t sim;
void init_ru_devices(void);
void init_RU(char*,clock_source_t clock_source,clock_source_t time_source,int send_dmrssync);
void *rfsim_top(void *n_frames);
void wait_RUs(void)
@@ -71,12 +74,12 @@ void wait_RUs(void)
// wait for all RUs to be configured over fronthaul
pthread_mutex_lock(&RC.ru_mutex);
while (RC.ru_mask>0) {
pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
}
pthread_mutex_unlock(&RC.ru_mutex);
// copy frame parameters from RU to UEs
for (i=0;i<NB_UE_INST;i++) {
sim.current_UE_rx_timestamp[i][0] = RC.ru[0]->frame_parms.samples_per_tti + RC.ru[0]->frame_parms.ofdm_symbol_size + RC.ru[0]->frame_parms.nb_prefix_samples0;
@@ -98,15 +101,14 @@ void RCConfig_sim(void) {
paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
// AssertFatal(RC.config_file_name!=NULL,"configuration file is undefined\n");
// Get num RU instances
config_getlist( &RUParamList,NULL,0, NULL);
RC.nb_RU = RUParamList.numelt;
AssertFatal(RC.nb_RU>0,"we need at least 1 RU for simulation\n");
printf("returned with %d rus\n",RC.nb_RU);
init_RU(NULL);
init_RU(NULL,internal,internal,0);
printf("Waiting for RUs to get set up\n");
wait_RUs();
+13 -12
View File
@@ -1,16 +1,16 @@
[*]
[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
[*] Tue Jun 5 09:36:17 2018
[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI
[*] Fri Aug 24 12:15:17 2018
[*]
[dumpfile] "/tmp/openair_dump_UE.vcd"
[dumpfile_mtime] "Tue Jun 5 09:22:52 2018"
[dumpfile_size] 23057775
[savefile] "/home/knopp/oai/openairinterface5g/targets/RT/USER/rru_if4p5_usrp.gtkw"
[timestart] 25050480000
[dumpfile] "/tmp/openair_rru_dump.vcd"
[dumpfile_mtime] "Fri Aug 24 12:10:15 2018"
[dumpfile_size] 27839039
[savefile] "/home/libra/oai/openairinterface5g/targets/RT/USER/rru_if4p5_usrp.gtkw"
[timestart] 10300310000
[size] 1301 716
[pos] 309 0
*-21.793451 29983948856 -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] 312
*-23.793451 29983948856 -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] 391
[signals_width] 262
[sst_expanded] 1
[sst_vpaned_height] 294
@@ -20,9 +20,11 @@ functions.trx_write
@24
variables.trx_write_flags[63:0]
@28
functions.trx_write_if
functions.send_if4
functions.trx_read_if
@29
functions.phy_procedures_ru_feprx0
@28
functions.phy_procedures_ru_feptx_ofdm0
functions.recv_if4
@24
variables.trx_ts[63:0]
@@ -30,7 +32,6 @@ variables.trx_tst[63:0]
variables.frame_number_RX0_RU[63:0]
variables.subframe_number_RX0_RU[63:0]
variables.frame_number_TX0_RU[63:0]
@25
variables.subframe_number_TX0_RU[63:0]
[pattern_trace] 1
[pattern_trace] 0
+743
View File
@@ -0,0 +1,743 @@
/*
* 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
*/
/*! \file ru_control.c
* \brief Top-level threads for RU entity
* \author R. Knopp, F. Kaltenberger, Navid Nikaein
* \date 2018
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
* \note
* \warning
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sched.h>
#include <linux/sched.h>
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>
#include <sys/sysinfo.h>
#include "rt_wrapper.h"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
#include "assertions.h"
#include "msc.h"
#include "PHY/types.h"
#include "PHY/defs_common.h"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
#include "../../ARCH/COMMON/common_lib.h"
#include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"
#include "PHY/phy_extern.h"
#include "LAYER2/MAC/mac_extern.h"
#include "PHY/LTE_TRANSPORT/transport_proto.h"
#include "SCHED/sched_eNB.h"
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
#include "PHY/INIT/phy_init.h"
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_extern.h"
#include "LAYER2/MAC/mac_proto.h"
#include "RRC/LTE/rrc_extern.h"
#include "PHY_INTERFACE/phy_interface.h"
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
#include "UTIL/OPT/opt.h"
#include "enb_config.h"
void configure_ru(int idx,
void *arg);
void configure_rru(int idx,
void *arg);
int attach_rru(RU_t *ru);
void fill_rf_config(RU_t *ru, char *rf_config_file);
void* ru_thread_control( void* param );
extern void reset_proc(RU_t *ru);
extern int setup_RU_buffers(RU_t *ru);
extern void phy_init_RU(RU_t*);
extern const char ru_states[6][9];
const char rru_format_options[4][20] = {"OAI_IF5_only","OAI_IF4p5_only","OAI_IF5_and_IF4p5","MBP_IF5"};
const char rru_formats[3][20] = {"OAI_IF5","MBP_IF5","OAI_IF4p5"};
const char ru_if_formats[4][20] = {"LOCAL_RF","REMOTE_OAI_IF5","REMOTE_MBP_IF5","REMOTE_OAI_IF4p5"};
extern int oai_exit;
extern void wait_eNBs(void);
int send_tick(RU_t *ru){
RRU_CONFIG_msg_t rru_config_msg;
rru_config_msg.type = RAU_tick;
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE;
LOG_I(PHY,"Sending RAU tick to RRU %d\n",ru->idx);
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
"RU %d cannot access remote radio\n",ru->idx);
return 0;
}
int send_config(RU_t *ru, RRU_CONFIG_msg_t rru_config_msg){
rru_config_msg.type = RRU_config;
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
LOG_I(PHY,"Sending Configuration to RRU %d (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d\n",ru->idx,
((RRU_config_t *)&rru_config_msg.msg[0])->num_bands,
((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0],
((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0],
((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0],
((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0],
((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0],
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0],
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0],
((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0],
((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0],
((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
"RU %d failed send configuration to remote radio\n",ru->idx);
return 0;
}
int send_capab(RU_t *ru){
RRU_CONFIG_msg_t rru_config_msg;
RRU_capabilities_t *cap;
int i=0;
rru_config_msg.type = RRU_capabilities;
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);
cap = (RRU_capabilities_t*)&rru_config_msg.msg[0];
LOG_I(PHY,"Sending Capabilities (len %d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",
(int)rru_config_msg.len,ru->num_bands,ru->max_pdschReferenceSignalPower,ru->max_rxgain,ru->nb_tx,ru->nb_rx);
switch (ru->function) {
case NGFI_RRU_IF4p5:
cap->FH_fmt = OAI_IF4p5_only;
break;
case NGFI_RRU_IF5:
cap->FH_fmt = OAI_IF5_only;
break;
case MBP_RRU_IF5:
cap->FH_fmt = MBP_IF5;
break;
default:
AssertFatal(1==0,"RU_function is unknown %d\n",RC.ru[0]->function);
break;
}
cap->num_bands = ru->num_bands;
for (i=0;i<ru->num_bands;i++) {
LOG_I(PHY,"Band %d: nb_rx %d nb_tx %d pdschReferenceSignalPower %d rxgain %d\n",
ru->band[i],ru->nb_rx,ru->nb_tx,ru->max_pdschReferenceSignalPower,ru->max_rxgain);
cap->band_list[i] = ru->band[i];
cap->nb_rx[i] = ru->nb_rx;
cap->nb_tx[i] = ru->nb_tx;
cap->max_pdschReferenceSignalPower[i] = ru->max_pdschReferenceSignalPower;
cap->max_rxgain[i] = ru->max_rxgain;
}
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
"RU %d failed send capabilities to RAU\n",ru->idx);
return 0;
}
int attach_rru(RU_t *ru) {
ssize_t msg_len,len;
RRU_CONFIG_msg_t rru_config_msg;
int received_capabilities=0;
wait_eNBs();
// Wait for capabilities
while (received_capabilities==0) {
memset((void*)&rru_config_msg,0,sizeof(rru_config_msg));
rru_config_msg.type = RAU_tick;
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE;
LOG_I(PHY,"Sending RAU tick to RRU %d\n",ru->idx);
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
"RU %d cannot access remote radio\n",ru->idx);
msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);
// wait for answer with timeout
if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
&rru_config_msg,
msg_len))<0) {
LOG_I(PHY,"Waiting for RRU %d\n",ru->idx);
}
else if (rru_config_msg.type == RRU_capabilities) {
AssertFatal(rru_config_msg.len==msg_len,"Received capabilities with incorrect length (%d!=%d)\n",(int)rru_config_msg.len,(int)msg_len);
LOG_I(PHY,"Received capabilities from RRU %d (len %d/%d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",ru->idx,
(int)rru_config_msg.len,(int)msg_len,
((RRU_capabilities_t*)&rru_config_msg.msg[0])->num_bands,
((RRU_capabilities_t*)&rru_config_msg.msg[0])->max_pdschReferenceSignalPower[0],
((RRU_capabilities_t*)&rru_config_msg.msg[0])->max_rxgain[0],
((RRU_capabilities_t*)&rru_config_msg.msg[0])->nb_tx[0],
((RRU_capabilities_t*)&rru_config_msg.msg[0])->nb_rx[0]);
received_capabilities=1;
}
else {
LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx);
}
}
configure_ru(ru->idx,
(RRU_capabilities_t *)&rru_config_msg.msg[0]);
rru_config_msg.type = RRU_config;
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
LOG_I(PHY,"Sending Configuration to RRU %d (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",ru->idx,
((RRU_config_t *)&rru_config_msg.msg[0])->num_bands,
((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0],
((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0],
((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0],
((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0],
((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0],
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0],
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0],
((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0],
((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0],
((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
"RU %d failed send configuration to remote radio\n",ru->idx);
return 0;
}
int connect_rau(RU_t *ru) {
RRU_CONFIG_msg_t rru_config_msg;
ssize_t msg_len;
int tick_received = 0;
int configuration_received = 0;
RRU_capabilities_t *cap;
int i;
int len;
// wait for RAU_tick
while (tick_received == 0) {
msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE;
if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
&rru_config_msg,
msg_len))<0) {
LOG_I(PHY,"Waiting for RAU\n");
}
else {
if (rru_config_msg.type == RAU_tick) {
LOG_I(PHY,"Tick received from RAU\n");
tick_received = 1;
}
else LOG_E(PHY,"Received erroneous message (%d)from RAU, expected RAU_tick\n",rru_config_msg.type);
}
}
// send capabilities
rru_config_msg.type = RRU_capabilities;
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);
cap = (RRU_capabilities_t*)&rru_config_msg.msg[0];
LOG_I(PHY,"Sending Capabilities (len %d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",
(int)rru_config_msg.len,ru->num_bands,ru->max_pdschReferenceSignalPower,ru->max_rxgain,ru->nb_tx,ru->nb_rx);
switch (ru->function) {
case NGFI_RRU_IF4p5:
cap->FH_fmt = OAI_IF4p5_only;
break;
case NGFI_RRU_IF5:
cap->FH_fmt = OAI_IF5_only;
break;
case MBP_RRU_IF5:
cap->FH_fmt = MBP_IF5;
break;
default:
AssertFatal(1==0,"RU_function is unknown %d\n",RC.ru[0]->function);
break;
}
cap->num_bands = ru->num_bands;
for (i=0;i<ru->num_bands;i++) {
LOG_I(PHY,"Band %d: nb_rx %d nb_tx %d pdschReferenceSignalPower %d rxgain %d\n",
ru->band[i],ru->nb_rx,ru->nb_tx,ru->max_pdschReferenceSignalPower,ru->max_rxgain);
cap->band_list[i] = ru->band[i];
cap->nb_rx[i] = ru->nb_rx;
cap->nb_tx[i] = ru->nb_tx;
cap->max_pdschReferenceSignalPower[i] = ru->max_pdschReferenceSignalPower;
cap->max_rxgain[i] = ru->max_rxgain;
}
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
"RU %d failed send capabilities to RAU\n",ru->idx);
// wait for configuration
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
while (configuration_received == 0) {
if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
&rru_config_msg,
rru_config_msg.len))<0) {
LOG_I(PHY,"Waiting for configuration from RAU\n");
}
else {
LOG_I(PHY,"Configuration received from RAU (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",
((RRU_config_t *)&rru_config_msg.msg[0])->num_bands,
((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0],
((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0],
((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0],
((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0],
((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0],
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0],
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0],
((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0],
((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0],
((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);
configure_rru(ru->idx,
(void*)&rru_config_msg.msg[0]);
configuration_received = 1;
}
}
return 0;
}
int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) {
FH_fmt_options_t fmt = cap->FH_fmt;
int i;
int found_band=0;
LOG_I(PHY,"RRU %d, num_bands %d, looking for band %d\n",ru->idx,cap->num_bands,ru->frame_parms.eutra_band);
for (i=0;i<cap->num_bands;i++) {
LOG_I(PHY,"band %d on RRU %d\n",cap->band_list[i],ru->idx);
if (ru->frame_parms.eutra_band == cap->band_list[i]) {
found_band=1;
break;
}
}
if (found_band == 0) {
LOG_I(PHY,"Couldn't find target EUTRA band %d on RRU %d\n",ru->frame_parms.eutra_band,ru->idx);
return(-1);
}
switch (ru->if_south) {
case LOCAL_RF:
AssertFatal(1==0, "This RU should not have a local RF, exiting\n");
return(0);
break;
case REMOTE_IF5:
if (fmt == OAI_IF5_only || fmt == OAI_IF5_and_IF4p5) return(0);
break;
case REMOTE_IF4p5:
if (fmt == OAI_IF4p5_only || fmt == OAI_IF5_and_IF4p5) return(0);
break;
case REMOTE_MBP_IF5:
if (fmt == MBP_IF5) return(0);
break;
default:
LOG_I(PHY,"No compatible Fronthaul interface found for RRU %d\n", ru->idx);
return(-1);
}
return(-1);
}
void configure_ru(int idx,
void *arg) {
RU_t *ru = RC.ru[idx];
RRU_config_t *config = (RRU_config_t *)arg;
RRU_capabilities_t *capabilities = (RRU_capabilities_t*)arg;
int ret;
LOG_I(PHY, "Received capabilities from RRU %d\n",idx);
if (capabilities->FH_fmt < MAX_FH_FMTs) LOG_I(PHY, "RU FH options %s\n",rru_format_options[capabilities->FH_fmt]);
AssertFatal((ret=check_capabilities(ru,capabilities)) == 0,
"Cannot configure RRU %d, check_capabilities returned %d\n", idx,ret);
// take antenna capabilities of RRU
ru->nb_tx = capabilities->nb_tx[0];
ru->nb_rx = capabilities->nb_rx[0];
// Pass configuration to RRU
LOG_I(PHY, "Using %s fronthaul (%d), band %d \n",ru_if_formats[ru->if_south],ru->if_south,ru->frame_parms.eutra_band);
// wait for configuration
config->FH_fmt = ru->if_south;
config->num_bands = 1;
config->band_list[0] = ru->frame_parms.eutra_band;
config->tx_freq[0] = ru->frame_parms.dl_CarrierFreq;
config->rx_freq[0] = ru->frame_parms.ul_CarrierFreq;
config->tdd_config[0] = ru->frame_parms.tdd_config;
config->tdd_config_S[0] = ru->frame_parms.tdd_config_S;
config->att_tx[0] = ru->att_tx;
config->att_rx[0] = ru->att_rx;
config->N_RB_DL[0] = ru->frame_parms.N_RB_DL;
config->N_RB_UL[0] = ru->frame_parms.N_RB_UL;
config->threequarter_fs[0] = ru->frame_parms.threequarter_fs;
if (ru->if_south==REMOTE_IF4p5) {
config->prach_FreqOffset[0] = ru->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset;
config->prach_ConfigIndex[0] = ru->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex;
LOG_I(PHY,"REMOTE_IF4p5: prach_FrequOffset %d, prach_ConfigIndex %d\n",
config->prach_FreqOffset[0],config->prach_ConfigIndex[0]);
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
int i;
for (i=0;i<4;i++) {
config->emtc_prach_CElevel_enable[0][i] = ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i];
config->emtc_prach_FreqOffset[0][i] = ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[i];
config->emtc_prach_ConfigIndex[0][i] = ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[i];
}
#endif
}
init_frame_parms(&ru->frame_parms,1);
phy_init_RU(ru);
}
void configure_rru(int idx,
void *arg) {
RRU_config_t *config = (RRU_config_t *)arg;
RU_t *ru = RC.ru[idx];
ru->frame_parms.eutra_band = config->band_list[0];
ru->frame_parms.dl_CarrierFreq = config->tx_freq[0];
ru->frame_parms.ul_CarrierFreq = config->rx_freq[0];
if (ru->frame_parms.dl_CarrierFreq == ru->frame_parms.ul_CarrierFreq) {
ru->frame_parms.frame_type = TDD;
ru->frame_parms.tdd_config = config->tdd_config[0];
ru->frame_parms.tdd_config_S = config->tdd_config_S[0];
}
else
ru->frame_parms.frame_type = FDD;
ru->att_tx = config->att_tx[0];
ru->att_rx = config->att_rx[0];
ru->frame_parms.N_RB_DL = config->N_RB_DL[0];
ru->frame_parms.N_RB_UL = config->N_RB_UL[0];
ru->frame_parms.threequarter_fs = config->threequarter_fs[0];
ru->frame_parms.pdsch_config_common.referenceSignalPower = ru->max_pdschReferenceSignalPower-config->att_tx[0];
if (ru->function==NGFI_RRU_IF4p5) {
ru->frame_parms.att_rx = ru->att_rx;
ru->frame_parms.att_tx = ru->att_tx;
LOG_I(PHY,"Setting ru->function to NGFI_RRU_IF4p5, prach_FrequOffset %d, prach_ConfigIndex %d, att (%d,%d)\n",
config->prach_FreqOffset[0],config->prach_ConfigIndex[0],ru->att_tx,ru->att_rx);
ru->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset = config->prach_FreqOffset[0];
ru->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex = config->prach_ConfigIndex[0];
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
for (int i=0;i<4;i++) {
ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i] = config->emtc_prach_CElevel_enable[0][i];
ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[i] = config->emtc_prach_FreqOffset[0][i];
ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[i] = config->emtc_prach_ConfigIndex[0][i];
}
#endif
}
init_frame_parms(&ru->frame_parms,1);
fill_rf_config(ru,ru->rf_config_file);
// phy_init_RU(ru);
}
void* ru_thread_control( void* param ) {
RU_t *ru = (RU_t*)param;
RU_proc_t *proc = &ru->proc;
RRU_CONFIG_msg_t rru_config_msg;
ssize_t msg_len;
int len;
// Start IF device if any
if (ru->start_if) {
LOG_I(PHY,"Starting IF interface for RU %d\n",ru->idx);
AssertFatal(
ru->start_if(ru,NULL) == 0, "Could not start the IF device\n");
if (ru->if_south != LOCAL_RF) wait_eNBs();
}
ru->state = (ru->function==eNodeB_3GPP)? RU_RUN : RU_IDLE;
LOG_I(PHY,"Control channel ON for RU %d\n", ru->idx);
while (!oai_exit) // Change the cond
{
msg_len = sizeof(RRU_CONFIG_msg_t); // TODO : check what should be the msg len
if (ru->state == RU_IDLE && ru->if_south != LOCAL_RF)
send_tick(ru);
if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
&rru_config_msg,
msg_len))<0) {
LOG_D(PHY,"Waiting msg for RU %d\n", ru->idx);
}
else
{
switch(rru_config_msg.type)
{
case RAU_tick: // RRU
if (ru->if_south != LOCAL_RF){
LOG_I(PHY,"Received Tick msg...Ignoring\n");
}else{
LOG_I(PHY,"Tick received from RAU\n");
if (send_capab(ru) == 0) ru->state = RU_CONFIG;
}
break;
case RRU_capabilities: // RAU
if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_capab msg...Ignoring\n");
else{
msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);
AssertFatal(rru_config_msg.len==msg_len,"Received capabilities with incorrect length (%d!=%d)\n",(int)rru_config_msg.len,(int)msg_len);
LOG_I(PHY,"Received capabilities from RRU %d (len %d/%d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",ru->idx,
(int)rru_config_msg.len,(int)msg_len,
((RRU_capabilities_t*)&rru_config_msg.msg[0])->num_bands,
((RRU_capabilities_t*)&rru_config_msg.msg[0])->max_pdschReferenceSignalPower[0],
((RRU_capabilities_t*)&rru_config_msg.msg[0])->max_rxgain[0],
((RRU_capabilities_t*)&rru_config_msg.msg[0])->nb_tx[0],
((RRU_capabilities_t*)&rru_config_msg.msg[0])->nb_rx[0]);
configure_ru(ru->idx,(RRU_capabilities_t *)&rru_config_msg.msg[0]);
// send config
if (send_config(ru,rru_config_msg) == 0) ru->state = RU_CONFIG;
}
break;
case RRU_config: // RRU
if (ru->if_south == LOCAL_RF){
LOG_I(PHY,"Configuration received from RAU (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",
((RRU_config_t *)&rru_config_msg.msg[0])->num_bands,
((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0],
((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0],
((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0],
((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0],
((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0],
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0],
((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0],
((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0],
((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0],
((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);
configure_rru(ru->idx, (void*)&rru_config_msg.msg[0]);
fill_rf_config(ru,ru->rf_config_file);
init_frame_parms(&ru->frame_parms,1);
ru->frame_parms.nb_antennas_rx = ru->nb_rx;
phy_init_RU(ru);
//if (ru->is_slave == 1) lte_sync_time_init(&ru->frame_parms);
if (ru->rfdevice.is_init != 1) openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
if (ru->rfdevice.trx_config_func) AssertFatal((ru->rfdevice.trx_config_func(&ru->rfdevice,&ru->openair0_cfg)==0),
"Failed to configure RF device for RU %d\n",ru->idx);
if (setup_RU_buffers(ru)!=0) {
printf("Exiting, cannot initialize RU Buffers\n");
exit(-1);
}
// send CONFIG_OK
rru_config_msg.type = RRU_config_ok;
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t);
LOG_I(PHY,"Sending CONFIG_OK to RAU %d\n", ru->idx);
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
"RU %d failed send CONFIG_OK to RAU\n",ru->idx);
reset_proc(ru);
ru->state = RU_READY;
} else LOG_E(PHY,"Received RRU_config msg...Ignoring\n");
break;
case RRU_config_ok: // RAU
if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_config_ok msg...Ignoring\n");
else{
if (setup_RU_buffers(ru)!=0) {
printf("Exiting, cannot initialize RU Buffers\n");
exit(-1);
}
// Set state to RUN for Master RU, Others on SYNC
ru->state = (ru->is_slave == 1) ? RU_SYNC : RU_RUN ;
ru->in_synch = 0;
LOG_I(PHY, "Signaling main thread that RU %d (is_slave %d) is ready in state %s\n",ru->idx,ru->is_slave,ru_states[ru->state]);
pthread_mutex_lock(&RC.ru_mutex);
RC.ru_mask &= ~(1<<ru->idx);
pthread_cond_signal(&RC.ru_cond);
pthread_mutex_unlock(&RC.ru_mutex);
wait_sync("ru_thread_control");
// send start
rru_config_msg.type = RRU_start;
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t); // TODO: set to correct msg len
LOG_I(PHY,"Sending Start to RRU %d\n", ru->idx);
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),"Failed to send msg to RU %d\n",ru->idx);
pthread_mutex_lock(&proc->mutex_ru);
proc->instance_cnt_ru = 1;
pthread_mutex_unlock(&proc->mutex_ru);
if (pthread_cond_signal(&proc->cond_ru_thread) != 0) {
LOG_E( PHY, "ERROR pthread_cond_signal for RU %d\n",ru->idx);
exit_fun( "ERROR pthread_cond_signal" );
break;
}
}
break;
case RRU_start: // RRU
if (ru->if_south == LOCAL_RF){
LOG_I(PHY,"Start received from RAU\n");
if (ru->state == RU_READY){
LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx);
pthread_mutex_lock(&RC.ru_mutex);
RC.ru_mask &= ~(1<<ru->idx);
pthread_cond_signal(&RC.ru_cond);
pthread_mutex_unlock(&RC.ru_mutex);
wait_sync("ru_thread_control");
ru->state = (ru->is_slave == 1) ? RU_SYNC : RU_RUN ;
ru->cmd = EMPTY;
pthread_mutex_lock(&proc->mutex_ru);
proc->instance_cnt_ru = 1;
pthread_mutex_unlock(&proc->mutex_ru);
if (pthread_cond_signal(&proc->cond_ru_thread) != 0) {
LOG_E( PHY, "ERROR pthread_cond_signal for RU %d\n",ru->idx);
exit_fun( "ERROR pthread_cond_signal" );
break;
}
}
else LOG_E(PHY,"RRU not ready, cannot start\n");
} else LOG_E(PHY,"Received RRU_start msg...Ignoring\n");
break;
case RRU_sync_ok: //RAU
if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_config_ok msg...Ignoring\n");
else{
if (ru->is_slave == 1){
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Received RRU_sync_ok from RRU %d\n",ru->idx);
// Just change the state of the RRU to unblock ru_thread()
ru->state = RU_RUN;
}else LOG_E(PHY,"Received RRU_sync_ok from a master RRU...Ignoring\n");
}
break;
case RRU_frame_resynch: //RRU
if (ru->if_south != LOCAL_RF) LOG_E(PHY,"Received RRU frame resynch message, should not happen in RAU\n");
else {
LOG_I(PHY,"Received RRU_frame_resynch command\n");
ru->cmd = RU_FRAME_RESYNCH;
ru->cmdval = ((uint16_t*)&rru_config_msg.msg[0])[0];
LOG_I(PHY,"Received Frame Resynch message with value %d\n",ru->cmdval);
}
break;
case RRU_stop: // RRU
if (ru->if_south == LOCAL_RF){
LOG_I(PHY,"Stop received from RAU\n");
if (ru->state == RU_RUN || ru->state == RU_ERROR){
LOG_I(PHY,"Stopping RRU\n");
ru->state = RU_READY;
// TODO: stop ru_thread
}else{
LOG_I(PHY,"RRU not running, can't stop\n");
}
}else LOG_E(PHY,"Received RRU_stop msg...Ignoring\n");
break;
default:
if (ru->if_south != LOCAL_RF){
if (ru->state == RU_IDLE){
// Keep sending TICK
send_tick(ru);
}
}
break;
} // switch
} //else
}//while
return(NULL);
}