Merging latest develop commits

This commit is contained in:
yilmazt
2019-07-16 11:20:24 +02:00
355 changed files with 13082 additions and 594202 deletions
+230 -179
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>
@@ -134,11 +146,11 @@ 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);
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
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);
void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru, int frame, int subframe);
#endif
@@ -150,10 +162,12 @@ 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)
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)
@@ -229,10 +243,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,
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++;
@@ -246,22 +257,22 @@ static inline int rxtx(PHY_VARS_eNB *eNB,
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);
@@ -276,6 +287,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,
//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,
@@ -284,6 +296,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,
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),
@@ -317,21 +330,25 @@ static inline int rxtx(PHY_VARS_eNB *eNB,
}
static void *L1_thread_tx(void *param) {
static void *L1_thread_tx(void *param)
{
L1_proc_t *eNB_proc = (L1_proc_t *)param;
L1_rxtx_proc_t *proc = &eNB_proc->L1_proc_tx;
PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id];
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
@@ -341,34 +358,42 @@ 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;
}
/*!
* \brief The RX UE-specific and TX thread of eNB.
* \param param is a \ref L1_proc_t structure which contains the info what to process.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
*/
static void *L1_thread( 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;
@@ -392,8 +417,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);
@@ -401,20 +428,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 );
@@ -423,11 +456,12 @@ static void *L1_thread( void *param ) {
return &eNB_thread_rxtx_status;
}
void eNB_top(PHY_VARS_eNB *eNB,
int frame_rx,
int subframe_rx,
char *string,
RU_t *ru)
int frame_rx,
int subframe_rx,
char *string,
RU_t *ru)
{
L1_proc_t *proc = &eNB->proc;
L1_rxtx_proc_t *L1_proc= &proc->L1_proc;
@@ -437,7 +471,7 @@ void eNB_top(PHY_VARS_eNB *eNB,
proc->subframe_rx = subframe_rx;
if (!oai_exit) {
T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
T(T_ENB_MASTER_TICK, T_INT(0), T_INT(ru_proc->frame_rx), T_INT(ru_proc->subframe_rx));
L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti);
L1_proc->frame_rx = ru_proc->frame_rx;
L1_proc->subframe_rx = ru_proc->tti_rx;
@@ -453,96 +487,119 @@ void eNB_top(PHY_VARS_eNB *eNB,
}
}
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;
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->tti_tx, proc->frame_rx, proc->subframe_rx);
return(-1);
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((ret=pthread_mutex_lock(&proc->mutex_RUs))==0, "mutex_lock returns %d\n",ret);
proc->instance_cnt_RUs = 0;
AssertFatal((ret=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
}
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->tti_rx&1,ru_proc->instance_cnt_eNBs );
exit_fun( "error locking mutex_eNB" );
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);
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->tti_tx = proc->subframe_tx;
ru_proc->frame_tx = proc->frame_tx;
ru_proc->timestamp_tx = timestamp_tx;
ru_proc->tti_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;
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);
}
int wakeup_tx(PHY_VARS_eNB *eNB,
int frame_rx,
int subframe_rx,
int frame_tx,
int subframe_tx,
uint64_t timestamp_tx)
{
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);
}
int wakeup_rxtx(PHY_VARS_eNB *eNB,
RU_t *ru)
{
@@ -550,44 +607,20 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,
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.
@@ -602,6 +635,13 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,
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");
@@ -609,22 +649,24 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,
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)
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);
@@ -638,11 +680,11 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,
}
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);
}
}
@@ -656,11 +698,7 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,
}
// 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
@@ -674,18 +712,23 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,
return;
}
pthread_mutex_unlock( &proc->mutex_prach );
AssertFatal((ret=pthread_mutex_unlock( &proc->mutex_prach))==0,"mutex_unlock return %d\n",ret);
}
}
#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) {
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]) {
@@ -700,11 +743,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);
}
}
@@ -718,11 +761,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
@@ -736,7 +775,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
@@ -747,7 +786,8 @@ void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
* \param param is a \ref L1_proc_t structure which contains the info what to process.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
*/
static void *eNB_thread_prach( void *param ) {
static void *eNB_thread_prach( void *param )
{
static int eNB_thread_prach_status;
PHY_VARS_eNB *eNB= (PHY_VARS_eNB *)param;
L1_proc_t *proc = &eNB->proc;
@@ -777,13 +817,15 @@ static void *eNB_thread_prach( void *param ) {
return &eNB_thread_prach_status;
}
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
/*!
* \brief The prach receive thread of eNB for BL/CE UEs.
* \param param is a \ref L1_proc_t structure which contains the info what to process.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
*/
static void *eNB_thread_prach_br( void *param ) {
static void *eNB_thread_prach_br( void *param )
{
static int eNB_thread_prach_status;
PHY_VARS_eNB *eNB= (PHY_VARS_eNB *)param;
L1_proc_t *proc = &eNB->proc;
@@ -806,17 +848,17 @@ static void *eNB_thread_prach_br( void *param ) {
eNB_thread_prach_status = 0;
return &eNB_thread_prach_status;
}
#endif
extern void init_td_thread(PHY_VARS_eNB *);
extern void init_te_thread(PHY_VARS_eNB *);
extern void kill_td_thread(PHY_VARS_eNB *);
extern void kill_te_thread(PHY_VARS_eNB *);
static void *process_stats_thread(void *param) {
static void *process_stats_thread(void *param)
{
PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param;
wait_sync("process_stats_thread");
@@ -849,7 +891,8 @@ static void *process_stats_thread(void *param) {
}
void init_eNB_proc(int inst) {
void init_eNB_proc(int inst)
{
/*int i=0;*/
int CC_id;
PHY_VARS_eNB *eNB;
@@ -880,7 +923,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);
@@ -971,15 +1014,16 @@ void init_eNB_proc(int inst) {
}
/*!
* \brief Terminate eNB TX and RX threads.
*/
void kill_eNB_proc(int inst) {
void kill_eNB_proc(int inst)
{
int *status;
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];
@@ -995,32 +1039,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");
@@ -1055,9 +1099,8 @@ void kill_eNB_proc(int inst) {
}
void reset_opp_meas(void) {
void reset_opp_meas(void)
{
int sfn;
reset_meas(&softmodem_stats_mt);
reset_meas(&softmodem_stats_hw);
@@ -1069,7 +1112,8 @@ void reset_opp_meas(void) {
}
void print_opp_meas(void) {
void print_opp_meas(void)
{
int sfn=0;
print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
@@ -1080,14 +1124,13 @@ void print_opp_meas(void) {
}
}
void free_transport(PHY_VARS_eNB *eNB) {
int i;
int j;
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
void free_transport(PHY_VARS_eNB *eNB)
{
for (int i=0; i<NUMBER_OF_UE_MAX; i++) {
LOG_D(PHY, "Freeing Transport Channel Buffers for DLSCH, UE %d\n",i);
for (j=0; j<2; j++) free_eNB_dlsch(eNB->dlsch[i][j]);
for (int j=0; j<2; j++) free_eNB_dlsch(eNB->dlsch[i][j]);
LOG_D(PHY, "Freeing Transport Channel Buffer for ULSCH, UE %d\n",i);
free_eNB_ulsch(eNB->ulsch[1+i]);
@@ -1096,7 +1139,9 @@ void free_transport(PHY_VARS_eNB *eNB) {
free_eNB_ulsch(eNB->ulsch[0]);
}
void init_transport(PHY_VARS_eNB *eNB) {
void init_transport(PHY_VARS_eNB *eNB)
{
int i;
int j;
LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
@@ -1156,7 +1201,9 @@ void init_transport(PHY_VARS_eNB *eNB) {
fp->pucch_config_common.deltaPUCCH_Shift = 1;
}
void init_eNB_afterRU(void) {
void init_eNB_afterRU(void)
{
int inst,CC_id,ru_id,i,aa;
PHY_VARS_eNB *eNB;
LOG_I(PHY,"%s() RC.nb_inst:%d\n", __FUNCTION__, RC.nb_inst);
@@ -1247,7 +1294,10 @@ void init_eNB_afterRU(void) {
}
}
void init_eNB(int single_thread_flag,int wait_for_sync) {
void init_eNB(int single_thread_flag,
int wait_for_sync)
{
int CC_id;
int inst;
PHY_VARS_eNB *eNB;
@@ -1291,7 +1341,8 @@ void init_eNB(int single_thread_flag,int wait_for_sync) {
}
void stop_eNB(int nb_inst) {
void stop_eNB(int nb_inst)
{
for (int inst=0; inst<nb_inst; inst++) {
LOG_I(PHY,"Killing eNB %d processing threads\n",inst);
kill_eNB_proc(inst);
+1087 -979
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -34,9 +34,11 @@
#include "UTIL/OPT/opt.h"
#include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.h"
#include <dlfcn.h>
static softmodem_params_t softmodem_params;
char *parallel_config=NULL;
char *worker_config=NULL;
double snr_dB=25;
uint64_t get_softmodem_optmask(void) {
return softmodem_params.optmask;
+33 -38
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;
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
@@ -284,7 +282,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();
@@ -521,7 +518,8 @@ static void wait_nfapi_init(char *thread_name) {
printf( "NFAPI: got sync (%s)\n", thread_name);
}
int main( int argc, char **argv ) {
int main ( int argc, char **argv )
{
int i;
int CC_id = 0;
int ru_id;
@@ -620,7 +618,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
@@ -630,58 +628,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);
@@ -709,7 +705,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
@@ -736,8 +731,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]);
}
}
@@ -755,17 +750,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");
+36 -25
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"
@@ -72,7 +74,7 @@
#define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n"
#define CONFIG_HLP_PRB "Set the PRB, valid values: 6, 25, 50, 100 \n"
#define CONFIG_HLP_EMULIFACE "Set the interface name for the multicast transport for emulation mode (e.g. eth0, lo, etc.) \n"
//#define CONFIG_HLP_NUMUES "Set the number of UEs for the emulation"
//#define CONFIG_HLP_NUMUES "Set the number of UEs for the emulation"
#define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n"
#define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n"
#define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n"
@@ -92,8 +94,8 @@
#define CONFIG_HLP_NOKRNMOD "(noS1 only): Use tun instead of namesh module \n"
#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n"
#define CONFIG_HLP_USRP_ARGS "set the arguments to identify USRP (same syntax as in UHD)\n"
#define CONFIG_HLP_USRP_CLK_SRC "USRP clock source: 'internal' or 'external'\n"
#define CONFIG_HLP_USRP_ARGS "set the arguments to identify USRP (same syntax as in UHD)\n"
#define CONFIG_HLP_USRP_CLK_SRC "USRP clock source: 'internal' or 'external'\n"
/***************************************************************************************************************************************/
/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument
@@ -150,7 +152,6 @@
{"usrp-clksrc", CONFIG_HLP_USRP_CLK_SRC,0, strptr:(char **)&usrp_clksrc, defstrval:"internal", TYPE_STRING, 0}, \
{"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \
{"clock", CONFIG_HLP_CLK, 0, uptr:&clock_source, defintval:0, TYPE_UINT, 0}, \
{"s" , CONFIG_HLP_SNR, 0, iptr:&snr_dB, defintval:25, TYPE_INT, 0}, \
{"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \
{"A", CONFIG_HLP_TADV, 0, iptr:&(timingadv), defintval:0, TYPE_INT, 0} \
}
@@ -182,6 +183,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)},\
@@ -196,6 +199,7 @@
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \
{"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \
{"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \
{"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \
{"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:0, TYPE_INT, 0}, \
{"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&EMULATE_RF, defintval:0, TYPE_INT, 0}, \
{"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)&parallel_config, defstrval:NULL, TYPE_STRING, 0}, \
@@ -305,7 +309,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)
@@ -324,6 +330,7 @@ uint64_t get_pdcp_optmask(void);
extern pthread_cond_t sync_cond;
extern pthread_mutex_t sync_mutex;
extern int sync_var;
extern double snr_dB;
extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
@@ -343,46 +350,50 @@ extern int transmission_mode;
extern double cpuf;
// In lte-enb.c
extern void init_eNB(int single_thread_flag,
int wait_for_sync);
extern void stop_eNB(int);
extern void kill_eNB_proc(int inst);
extern void init_eNB(int single_thread_flag,
int wait_for_sync);
// In lte-ru.c
extern void init_RU(char *);
extern void stop_ru(RU_t *ru);
extern void init_ru_vnf(void);
extern void init_RU_proc(RU_t *ru);
extern void stop_RU(int nb_ru);
extern void kill_RU_proc(RU_t *ru);
extern void set_function_spec_param(RU_t *ru);
extern void init_RU(char*,
clock_source_t clock_source,
clock_source_t time_source,
int send_dmrssync);
// In lte-ue.c
extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue,
openair0_config_t *openair0_cfg);
openair0_config_t *openair0_cfg);
extern void fill_ue_band_info(void);
extern void init_UE(int nb_inst,
int eMBMS_active,
int uecap_xer_in,
int timing_correction,
int phy_test,
int UE_scan,
int UE_scan_carrier,
runmode_t mode,
int rxgain,
int txpowermax,
int eMBMS_active,
int uecap_xer_in,
int timing_correction,
int phy_test,
int UE_scan,
int UE_scan_carrier,
runmode_t mode,
int rxgain,
int txpowermax,
LTE_DL_FRAME_PARMS *fp);
extern void init_thread(int sched_runtime,
int sched_deadline,
int sched_fifo,
cpu_set_t *cpuset,
char *name);
int sched_deadline,
int sched_fifo,
cpu_set_t *cpuset,
char *name);
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
extern void init_td_thread(PHY_VARS_eNB *);
extern void init_te_thread(PHY_VARS_eNB *);
extern void kill_td_thread(PHY_VARS_eNB *);
@@ -395,15 +406,15 @@ extern void init_ue_devices(PHY_VARS_UE *);
PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t UE_id,
uint8_t abstraction_flag);
void init_eNB_afterRU(void);
extern int stop_L1L2(module_id_t enb_id);
extern int restart_L1L2(module_id_t enb_id);
extern void init_UE_stub_single_thread(int nb_inst,
int eMBMS_active,
int uecap_xer_in,
char *emul_iface);
int uecap_xer_in,
char *emul_iface);
extern PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t UE_id,
+2 -2
View File
@@ -910,7 +910,7 @@ void ue_stub_rx_handler(unsigned int num_bytes,
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:
@@ -1767,7 +1767,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();
}
}
+7 -6
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;
@@ -131,8 +132,6 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
int UE_scan = 1;
int UE_scan_carrier = 0;
int snr_dB=25;
runmode_t mode = normal_txrx;
FILE *input_fd=NULL;
@@ -319,10 +318,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
@@ -610,7 +611,7 @@ int main( int argc, char **argv ) {
if (config_mod == NULL) {
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
}
mode = normal_txrx;
memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
set_latency_target();
@@ -810,7 +811,7 @@ int main( int argc, char **argv ) {
//p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
if (IS_SOFTMODEM_SIML1 ) {
init_ocm((double)snr_dB,0);
init_ocm(snr_dB,0);
PHY_vars_UE_g[0][0]->no_timing_correction = 1;
}
+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
+736
View File
@@ -0,0 +1,736 @@
/*
* 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 "common/utils/LOG/log.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"
int attach_rru(RU_t *ru);
void configure_ru(int idx, void *arg);
void configure_rru(int idx, void *arg);
void fill_rf_config(RU_t *ru, char *rf_config_file);
void* ru_thread_control( void* param );
extern int setup_RU_buffers(RU_t *ru);
extern void reset_proc(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 (LTE_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) {
LOG_I(PHY,"Setting RRU to TDD frame type\n");
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 (LTE_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);
}