Merge remote-tracking branch 'origin/develop-nr' into nr_prach
Conflicts: cmake_targets/build_oai executables/nr-gnb.c openair1/PHY/INIT/nr_init.c openair1/PHY/defs_gNB.h openair1/SCHED_NR/fapi_nr_l1.c openair2/LAYER2/NR_MAC_gNB/config.c openair2/LAYER2/NR_MAC_gNB/mac_proto.h openair2/RRC/NR/rrc_gNB.c
This commit is contained in:
+150
-133
@@ -135,8 +135,8 @@ extern double cpuf;
|
||||
void init_gNB(int,int);
|
||||
void stop_gNB(int nb_inst);
|
||||
|
||||
int wakeup_txfh(gNB_L1_rxtx_proc_t *proc,PHY_VARS_gNB *gNB);
|
||||
int wakeup_tx(PHY_VARS_gNB *gNB);
|
||||
int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot_tx,uint64_t timestamp_tx);
|
||||
int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_tx,uint64_t timestamp_tx);
|
||||
extern PARALLEL_CONF_t get_thread_parallel_conf(void);
|
||||
extern WORKER_CONF_t get_thread_worker_conf(void);
|
||||
|
||||
@@ -151,20 +151,18 @@ extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
|
||||
#define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials)
|
||||
|
||||
|
||||
static inline int rxtx(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc, char *thread_name) {
|
||||
static inline int rxtx(PHY_VARS_gNB *gNB,int frame_rx, int slot_rx, int frame_tx, int slot_tx, char *thread_name) {
|
||||
start_meas(&softmodem_stats_rxtx_sf);
|
||||
|
||||
// *******************************************************************
|
||||
|
||||
if (nfapi_mode == 1) {
|
||||
// I am a PNF and I need to let nFAPI know that we have a (sub)frame tick
|
||||
uint16_t frame = proc->frame_rx;
|
||||
uint16_t slot = proc->slot_rx;
|
||||
//add_subframe(&frame, &subframe, 4);
|
||||
//oai_subframe_ind(proc->frame_tx, proc->subframe_tx);
|
||||
//LOG_D(PHY, "oai_subframe_ind(frame:%u, subframe:%d) - NOT CALLED ********\n", frame, subframe);
|
||||
start_meas(&nfapi_meas);
|
||||
oai_subframe_ind(frame, slot);
|
||||
oai_subframe_ind(frame_rx, slot_rx);
|
||||
stop_meas(&nfapi_meas);
|
||||
|
||||
if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus||
|
||||
@@ -179,15 +177,15 @@ static inline int rxtx(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc, char *thread_
|
||||
NFAPI_SFNSF2DEC(gNB->UL_INFO.crc_ind.sfn_sf), gNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs,
|
||||
NFAPI_SFNSF2DEC(gNB->UL_INFO.rach_ind.sfn_sf), gNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles,
|
||||
gNB->UL_INFO.cqi_ind.number_of_cqis,
|
||||
proc->frame_rx, proc->slot_rx,
|
||||
proc->frame_tx, proc->slot_tx);
|
||||
frame_rx, slot_rx,
|
||||
frame_tx, slot_tx);
|
||||
}
|
||||
}
|
||||
|
||||
/// NR disabling
|
||||
// ****************************************
|
||||
// Common RX procedures subframe n
|
||||
T(T_GNB_PHY_DL_TICK, T_INT(gNB->Mod_id), T_INT(proc->frame_tx), T_INT(proc->slot_tx));
|
||||
T(T_GNB_PHY_DL_TICK, T_INT(gNB->Mod_id), T_INT(frame_tx), T_INT(slot_tx));
|
||||
/*
|
||||
// if this is IF5 or 3GPP_gNB
|
||||
if (gNB && gNB->RU_list && gNB->RU_list[0] && gNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
|
||||
@@ -200,8 +198,8 @@ static inline int rxtx(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc, char *thread_
|
||||
}
|
||||
*/
|
||||
pthread_mutex_lock(&gNB->UL_INFO_mutex);
|
||||
gNB->UL_INFO.frame = proc->frame_rx;
|
||||
gNB->UL_INFO.slot = proc->slot_rx;
|
||||
gNB->UL_INFO.frame = frame_rx;
|
||||
gNB->UL_INFO.slot = slot_rx;
|
||||
gNB->UL_INFO.module_id = gNB->Mod_id;
|
||||
gNB->UL_INFO.CC_id = gNB->CC_id;
|
||||
gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
|
||||
@@ -217,12 +215,12 @@ static inline int rxtx(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc, char *thread_
|
||||
|
||||
if (oai_exit) return(-1);
|
||||
|
||||
if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) {
|
||||
phy_procedures_gNB_TX(gNB, proc, 1);
|
||||
if(get_thread_parallel_conf() != PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
|
||||
}
|
||||
|
||||
stop_meas( &softmodem_stats_rxtx_sf );
|
||||
LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, proc->frame_rx, proc->slot_rx, proc->frame_tx, proc->slot_tx);
|
||||
LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx);
|
||||
#if 0
|
||||
LOG_D(PHY, "rxtx:%lld nfapi:%lld phy:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ",
|
||||
softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now,
|
||||
@@ -268,17 +266,14 @@ static inline int rxtx(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc, char *thread_
|
||||
static void *gNB_L1_thread_tx(void *param) {
|
||||
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
|
||||
gNB_L1_proc_t *gNB_proc = &gNB->proc;
|
||||
gNB_L1_rxtx_proc_t *proc = &gNB_proc->L1_proc_tx;
|
||||
gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB_proc->L1_proc_tx;
|
||||
//PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id];
|
||||
char thread_name[100];
|
||||
sprintf(thread_name,"TXnp4_%d\n",&gNB->proc.L1_proc == proc ? 0 : 1);
|
||||
|
||||
//wait_sync("tx_thread");
|
||||
sprintf(thread_name,"gNB_L1_thread_tx\n");
|
||||
|
||||
while (!oai_exit) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 );
|
||||
|
||||
if (wait_on_condition(&proc->mutex,&proc->cond,&proc->instance_cnt,thread_name)<0) break;
|
||||
if (wait_on_condition(&L1_proc_tx->mutex,&L1_proc_tx->cond,&L1_proc_tx->instance_cnt,thread_name)<0) break;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 1 );
|
||||
|
||||
@@ -289,22 +284,24 @@ static void *gNB_L1_thread_tx(void *param) {
|
||||
// run PHY TX procedures the one after the other for all CCs to avoid race conditions
|
||||
// (may be relaxed in the future for performance reasons)
|
||||
// *****************************************
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX1_GNB,proc->slot_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX1_GNB,proc->slot_rx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_GNB,proc->frame_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_GNB,proc->frame_rx);
|
||||
phy_procedures_gNB_TX(gNB, proc, 1);
|
||||
pthread_mutex_lock( &proc->mutex );
|
||||
proc->instance_cnt = -1;
|
||||
int frame_tx = L1_proc_tx->frame_tx;
|
||||
int slot_tx = L1_proc_tx->slot_tx;
|
||||
uint64_t timestamp_tx = L1_proc_tx->timestamp_tx;
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX1_GNB,slot_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_GNB,frame_tx);
|
||||
phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
|
||||
pthread_mutex_lock( &L1_proc_tx->mutex );
|
||||
L1_proc_tx->instance_cnt = -1;
|
||||
|
||||
// the thread can now be woken up
|
||||
if (pthread_cond_signal(&proc->cond) != 0) {
|
||||
if (pthread_cond_signal(&L1_proc_tx->cond) != 0) {
|
||||
LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n");
|
||||
exit_fun( "ERROR pthread_cond_signal" );
|
||||
}
|
||||
pthread_mutex_unlock(&L1_proc_tx->mutex);
|
||||
|
||||
pthread_mutex_unlock( &proc->mutex );
|
||||
wakeup_txfh(proc,gNB);
|
||||
wakeup_txfh(gNB,L1_proc_tx,frame_tx,slot_tx,timestamp_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 );
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -320,41 +317,43 @@ static void *gNB_L1_thread( void *param ) {
|
||||
static int gNB_thread_rxtx_status;
|
||||
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
|
||||
gNB_L1_proc_t *gNB_proc = &gNB->proc;
|
||||
gNB_L1_rxtx_proc_t *proc = &gNB_proc->L1_proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc = &gNB_proc->L1_proc;
|
||||
//PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id];
|
||||
char thread_name[100];
|
||||
|
||||
// set default return value
|
||||
gNB_thread_rxtx_status = 0;
|
||||
sprintf(thread_name,"RXn_TXnp4_%d",&gNB->proc.L1_proc == proc ? 0 : 1);
|
||||
|
||||
sprintf(thread_name,"gNB_L1_thread");
|
||||
|
||||
|
||||
while (!oai_exit) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 );
|
||||
|
||||
if (wait_on_condition(&proc->mutex,&proc->cond,&proc->instance_cnt,thread_name)<0) break;
|
||||
|
||||
if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break;
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX0_GNB,proc->slot_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,proc->slot_rx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_GNB,proc->frame_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_GNB,proc->frame_rx);
|
||||
|
||||
int frame_rx = L1_proc->frame_rx;
|
||||
int slot_rx = L1_proc->slot_rx;
|
||||
int frame_tx = L1_proc->frame_tx;
|
||||
int slot_tx = L1_proc->slot_tx;
|
||||
uint64_t timestamp_tx = L1_proc->timestamp_tx;
|
||||
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX0_GNB,slot_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,slot_rx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_GNB,frame_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_GNB,frame_rx);
|
||||
|
||||
if (oai_exit) break;
|
||||
|
||||
if (gNB->CC_id==0) {
|
||||
if (rxtx(gNB,proc,thread_name) < 0) break;
|
||||
if (rxtx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,thread_name) < 0) break;
|
||||
}
|
||||
|
||||
if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) {
|
||||
phy_procedures_gNB_TX(gNB, proc, 1);
|
||||
}
|
||||
if (release_thread(&L1_proc->mutex,&L1_proc->instance_cnt,thread_name)<0) break;
|
||||
|
||||
if (release_thread(&proc->mutex,&proc->instance_cnt,thread_name)<0) break;
|
||||
|
||||
if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
wakeup_tx(gNB);
|
||||
} else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) {
|
||||
wakeup_txfh(proc,gNB);
|
||||
}
|
||||
if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,timestamp_tx);
|
||||
else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) wakeup_txfh(gNB,L1_proc,frame_tx,slot_tx,timestamp_tx);
|
||||
} // while !oai_exit
|
||||
|
||||
LOG_D(PHY, " *** Exiting gNB thread RXn_TXnp4\n");
|
||||
@@ -402,7 +401,7 @@ void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, char *string, struct
|
||||
L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-sl_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
|
||||
L1_proc->slot_tx = (L1_proc->slot_rx + sl_ahead)%fp->slots_per_frame;
|
||||
|
||||
if (rxtx(gNB,L1_proc,string) < 0) LOG_E(PHY,"gNB %d CC_id %d failed during execution\n",gNB->Mod_id,gNB->CC_id);
|
||||
if (rxtx(gNB,L1_proc->frame_rx,L1_proc->slot_rx,L1_proc->frame_tx,L1_proc->slot_tx,string) < 0) LOG_E(PHY,"gNB %d CC_id %d failed during execution\n",gNB->Mod_id,gNB->CC_id);
|
||||
|
||||
ru_proc->timestamp_tx = L1_proc->timestamp_tx;
|
||||
ru_proc->tti_tx = L1_proc->slot_tx;
|
||||
@@ -410,92 +409,116 @@ void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, char *string, struct
|
||||
}
|
||||
}
|
||||
|
||||
int wakeup_txfh(gNB_L1_rxtx_proc_t *proc,PHY_VARS_gNB *gNB) {
|
||||
int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot_tx,uint64_t timestamp_tx) {
|
||||
|
||||
RU_t *ru;
|
||||
RU_proc_t *ru_proc;
|
||||
|
||||
int waitret,ret;
|
||||
struct timespec wait;
|
||||
wait.tv_sec=0;
|
||||
wait.tv_nsec=5000000L;
|
||||
//printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~inside wakeup_txfh %d.%d IC_RU = %d\n", proc->frame_tx, proc->slot_tx, proc->instance_cnt_RUs);
|
||||
wait.tv_nsec=10000000L;
|
||||
|
||||
|
||||
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->slot_tx);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&gNB->proc.mutex_RU_tx);
|
||||
gNB->proc.RU_mask_tx = 0;
|
||||
pthread_mutex_unlock(&gNB->proc.mutex_RU_tx);
|
||||
// note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1);
|
||||
waitret=timedwait_on_condition(&proc->mutex_RUs_tx,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh",1000000);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0);
|
||||
|
||||
if (release_thread(&proc->mutex_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")<0) return(-1);
|
||||
AssertFatal(release_thread(&proc->mutex_RUs_tx,&proc->instance_cnt_RUs,"wakeup_txfh")==0, "error releaseing gNB lock on RUs\n");
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
|
||||
|
||||
for(int i=0; i<gNB->num_RU; i++) {
|
||||
if (waitret == ETIMEDOUT) {
|
||||
LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx);
|
||||
|
||||
AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
|
||||
gNB->proc.RU_mask_tx = 0;
|
||||
AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==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_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0);
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
for(int i=0; i<gNB->num_RU; i++)
|
||||
{
|
||||
ru = gNB->RU_list[i];
|
||||
ru_proc = &ru->proc;
|
||||
|
||||
AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret);
|
||||
|
||||
if (ru_proc->instance_cnt_gNBs == 0) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1);
|
||||
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->slot_rx);
|
||||
return(-1);
|
||||
}
|
||||
AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
|
||||
gNB->proc.RU_mask_tx = 0;
|
||||
AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
AssertFatal((ret=pthread_mutex_unlock( &ru_proc->mutex_gNBs ))==0,"mutex_unlock return %d\n",ret);
|
||||
|
||||
if (pthread_mutex_timedlock(&ru_proc->mutex_gNBs,&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_gNBs );
|
||||
exit_fun( "error locking mutex_gNB" );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 0);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
ru_proc->instance_cnt_gNBs = 0;
|
||||
ru_proc->timestamp_tx = proc->timestamp_tx;
|
||||
ru_proc->tti_tx = proc->slot_tx;
|
||||
ru_proc->frame_tx = proc->frame_tx;
|
||||
LOG_I(PHY,"Signaling tx_thread_fh for %d.%d\n",ru_proc->frame_tx,ru_proc->tti_tx);
|
||||
ru_proc->timestamp_tx = timestamp_tx;
|
||||
ru_proc->tti_tx = slot_tx;
|
||||
ru_proc->frame_tx = frame_tx;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, ru_proc->instance_cnt_gNBs);
|
||||
|
||||
LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx);
|
||||
// the thread can now be woken up
|
||||
if (pthread_cond_signal(&ru_proc->cond_gNBs) != 0) {
|
||||
LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n");
|
||||
exit_fun( "ERROR pthread_cond_signal" );
|
||||
return(-1);
|
||||
}
|
||||
AssertFatal(pthread_cond_signal(&ru_proc->cond_gNBs) == 0,
|
||||
"[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n");
|
||||
AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_gNBs))==0,"mutex_unlock returned %d\n",ret);
|
||||
|
||||
pthread_mutex_unlock( &ru_proc->mutex_gNBs );
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int wakeup_tx(PHY_VARS_gNB *gNB) {
|
||||
gNB_L1_proc_t *proc=&gNB->proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc_tx = &proc->L1_proc_tx;
|
||||
gNB_L1_rxtx_proc_t *L1_proc = &proc->L1_proc;
|
||||
int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_tx,uint64_t timestamp_tx) {
|
||||
|
||||
|
||||
gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB->proc.L1_proc_tx;
|
||||
|
||||
int ret;
|
||||
|
||||
struct timespec wait;
|
||||
wait.tv_sec=0;
|
||||
wait.tv_nsec=5000000L;
|
||||
|
||||
|
||||
AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
while(L1_proc_tx->instance_cnt == 0) {
|
||||
while(L1_proc_tx->instance_cnt == 0){
|
||||
pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex);
|
||||
}
|
||||
|
||||
L1_proc_tx->instance_cnt = 0;
|
||||
L1_proc_tx->slot_rx = L1_proc->slot_rx;
|
||||
L1_proc_tx->frame_rx = L1_proc->frame_rx;
|
||||
L1_proc_tx->slot_tx = L1_proc->slot_tx;
|
||||
L1_proc_tx->frame_tx = L1_proc->frame_tx;
|
||||
L1_proc_tx->timestamp_tx = L1_proc->timestamp_tx;
|
||||
|
||||
|
||||
L1_proc_tx->slot_rx = slot_rx;
|
||||
L1_proc_tx->frame_rx = frame_rx;
|
||||
L1_proc_tx->slot_tx = slot_tx;
|
||||
L1_proc_tx->frame_tx = frame_tx;
|
||||
L1_proc_tx->timestamp_tx = timestamp_tx;
|
||||
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,1);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,0);
|
||||
|
||||
// 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);
|
||||
}
|
||||
AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for gNB L1 thread\n");
|
||||
|
||||
AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret);
|
||||
|
||||
pthread_mutex_unlock( &L1_proc_tx->mutex);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -504,56 +527,48 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
|
||||
gNB_L1_rxtx_proc_t *L1_proc=&proc->L1_proc;
|
||||
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
|
||||
RU_proc_t *ru_proc=&ru->proc;
|
||||
int ret;
|
||||
int i;
|
||||
struct timespec wait;
|
||||
pthread_mutex_lock(&proc->mutex_RU);
|
||||
|
||||
for (i=0; i<gNB->num_RU; i++) {
|
||||
|
||||
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret);
|
||||
for (i=0;i<gNB->num_RU;i++) {
|
||||
if (ru == gNB->RU_list[i]) {
|
||||
if ((proc->RU_mask&(1<<i)) > 0)
|
||||
LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
|
||||
gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask);
|
||||
|
||||
LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
|
||||
gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask);
|
||||
proc->RU_mask |= (1<<i);
|
||||
}
|
||||
}
|
||||
|
||||
if (proc->RU_mask != (1<<gNB->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);
|
||||
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"mutex_unlock returns %d\n",ret);
|
||||
return(0);
|
||||
} else { // all RUs have provided their information so continue on and wakeup gNB processing
|
||||
proc->RU_mask = 0;
|
||||
pthread_mutex_unlock(&proc->mutex_RU);
|
||||
}
|
||||
else { // all RUs have provided their information so continue on and wakeup gNB processing
|
||||
proc->RU_mask = 0;
|
||||
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"muex_unlock returns %d\n",ret);
|
||||
}
|
||||
|
||||
|
||||
wait.tv_sec=0;
|
||||
wait.tv_nsec=5000000L;
|
||||
|
||||
/* accept some delay in processing - up to 5ms */
|
||||
for (i = 0; i < fp->slots_per_frame && L1_proc->instance_cnt == 0; i++) {
|
||||
LOG_W( PHY,"[gNB] SFN.SL %d.%d, gNB RXn-TXnp4 thread busy!! (i %d, cnt %i)\n", L1_proc->frame_tx, L1_proc->slot_tx, i,L1_proc->instance_cnt);
|
||||
usleep(100);
|
||||
}
|
||||
|
||||
if (L1_proc->instance_cnt == 0) {
|
||||
exit_fun( "TX thread busy" );
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// wake up TX for subframe n+sl_ahead
|
||||
// lock the TX mutex and make sure the thread is ready
|
||||
if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) {
|
||||
LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB RXTX thread %d (IC %d)\n", L1_proc->slot_rx&1,L1_proc->instance_cnt );
|
||||
exit_fun( "error locking mutex" );
|
||||
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,"muex_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->tti_rx);
|
||||
}
|
||||
|
||||
++L1_proc->instance_cnt;
|
||||
// We have just received and processed the common part of a subframe, say n.
|
||||
// TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired
|
||||
|
||||
// We have just received and processed the common part of a subframe, say n.
|
||||
// TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired
|
||||
// transmitted timestamp of the next TX slot (first).
|
||||
// The last (TS_rx mod samples_per_frame) was n*samples_per_tti,
|
||||
// The last (TS_rx mod samples_per_frame) was n*samples_per_tti,
|
||||
// we want to generate subframe (n+sl_ahead), so TS_tx = TX_rx+sl_ahead*samples_per_tti,
|
||||
// and proc->slot_tx = proc->slot_rx+sl_ahead
|
||||
L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sl_ahead*fp->samples_per_slot);
|
||||
@@ -561,7 +576,10 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
|
||||
L1_proc->slot_rx = ru_proc->tti_rx;
|
||||
L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-sl_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
|
||||
L1_proc->slot_tx = (L1_proc->slot_rx + sl_ahead)%fp->slots_per_frame;
|
||||
LOG_I(PHY,"wakeupL1: passing parameter IC = %d, RX: %d.%d, TX: %d.%d to L1 sl_ahead = %d\n", L1_proc->instance_cnt, L1_proc->frame_rx, L1_proc->slot_rx, L1_proc->frame_tx, L1_proc->slot_tx, sl_ahead);
|
||||
|
||||
LOG_D(PHY,"wakeupL1: passing parameter IC = %d, RX: %d.%d, TX: %d.%d to L1 sl_ahead = %d\n", L1_proc->instance_cnt, L1_proc->frame_rx, L1_proc->slot_rx, L1_proc->frame_tx, L1_proc->slot_tx, sl_ahead);
|
||||
|
||||
pthread_mutex_unlock( &L1_proc->mutex );
|
||||
|
||||
// the thread can now be woken up
|
||||
if (pthread_cond_signal(&L1_proc->cond) != 0) {
|
||||
@@ -569,8 +587,7 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
|
||||
exit_fun( "ERROR pthread_cond_signal" );
|
||||
return(-1);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock( &L1_proc->mutex );
|
||||
|
||||
return(0);
|
||||
}
|
||||
/*
|
||||
|
||||
+61
-53
@@ -297,27 +297,27 @@ int connect_rau(RU_t *ru) {
|
||||
/* Southbound Fronthaul functions, RCC/RAU */
|
||||
|
||||
// southbound IF5 fronthaul for 16-bit OAI format
|
||||
static inline void fh_if5_south_out(RU_t *ru) {
|
||||
static inline void fh_if5_south_out(RU_t *ru,int frame,int slot,uint64_t timestamp) {
|
||||
if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
|
||||
|
||||
send_IF5(ru, ru->proc.timestamp_tx, ru->proc.tti_tx, &ru->seqno, IF5_RRH_GW_DL);
|
||||
send_IF5(ru, timestamp, slot, &ru->seqno, IF5_RRH_GW_DL);
|
||||
}
|
||||
|
||||
// southbound IF5 fronthaul for Mobipass packet format
|
||||
static inline void fh_if5_mobipass_south_out(RU_t *ru) {
|
||||
static inline void fh_if5_mobipass_south_out(RU_t *ru,int frame,int slot,uint64_t timestamp) {
|
||||
if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
|
||||
|
||||
send_IF5(ru, ru->proc.timestamp_tx, ru->proc.tti_tx, &ru->seqno, IF5_MOBIPASS);
|
||||
send_IF5(ru, timestamp, slot, &ru->seqno, IF5_MOBIPASS);
|
||||
}
|
||||
|
||||
// southbound IF4p5 fronthaul
|
||||
static inline void fh_if4p5_south_out(RU_t *ru) {
|
||||
static inline void fh_if4p5_south_out(RU_t *ru,int frame,int slot, uint64_t timestamp) {
|
||||
if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
|
||||
|
||||
LOG_D(PHY,"Sending IF4p5 for frame %d subframe %d\n",ru->proc.frame_tx,ru->proc.tti_tx);
|
||||
|
||||
if (nr_slot_select(&ru->gNB_list[0]->gNB_config,ru->proc.tti_tx)!=SF_UL)
|
||||
send_IF4p5(ru,ru->proc.frame_tx, ru->proc.tti_tx, IF4p5_PDLFFT);
|
||||
send_IF4p5(ru,frame, slot, IF4p5_PDLFFT);
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
@@ -564,9 +564,9 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot_tx );
|
||||
}
|
||||
|
||||
if (ru->feptx_ofdm) ru->feptx_ofdm(ru);
|
||||
if (ru->feptx_ofdm) ru->feptx_ofdm(ru,frame_tx,slot_tx);
|
||||
|
||||
if (ru->fh_south_out) ru->fh_south_out(ru);
|
||||
if (ru->fh_south_out) ru->fh_south_out(ru,frame_tx,slot_tx,proc->timestamp_tx);
|
||||
}
|
||||
|
||||
void fh_if5_north_out(RU_t *ru) {
|
||||
@@ -657,7 +657,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
|
||||
proc->timestamp_rx = 0;
|
||||
} else {
|
||||
if (proc->timestamp_rx - old_ts != fp->samples_per_slot) {
|
||||
LOG_I(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_slot,ru->ts_offset);
|
||||
LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_slot,ru->ts_offset);
|
||||
ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_slot);
|
||||
proc->timestamp_rx = ts-ru->ts_offset;
|
||||
}
|
||||
@@ -669,7 +669,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
|
||||
proc->timestamp_tx = proc->timestamp_rx+(sl_ahead*fp->samples_per_slot);
|
||||
proc->tti_tx = (proc->tti_rx+sl_ahead)%fp->slots_per_frame;
|
||||
proc->frame_tx = (proc->tti_rx>(fp->slots_per_frame-1-sl_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
|
||||
LOG_I(PHY,"RU %d/%d TS %llu (off %d), frame %d, slot %d.%d / %d\n",
|
||||
LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, slot %d.%d / %d\n",
|
||||
ru->idx,
|
||||
0,
|
||||
(unsigned long long int)proc->timestamp_rx,
|
||||
@@ -707,16 +707,16 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
|
||||
}
|
||||
|
||||
|
||||
void tx_rf(RU_t *ru) {
|
||||
void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
nfapi_nr_config_request_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
void *txp[ru->nb_tx];
|
||||
unsigned int txs;
|
||||
int i;
|
||||
T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(proc->frame_tx), T_INT(proc->tti_tx),
|
||||
T_INT(0), T_BUFFER(&ru->common.txdata[0][proc->tti_tx * fp->samples_per_slot], fp->samples_per_slot * 4));
|
||||
nr_subframe_t SF_type = nr_slot_select(cfg,proc->tti_tx%fp->slots_per_frame);
|
||||
T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(frame), T_INT(slot),
|
||||
T_INT(0), T_BUFFER(&ru->common.txdata[0][slot * fp->samples_per_slot], fp->samples_per_slot * 4));
|
||||
nr_subframe_t SF_type = nr_slot_select(cfg,slot%fp->slots_per_frame);
|
||||
int sf_extension = 0;
|
||||
|
||||
if ((SF_type == SF_DL) ||
|
||||
@@ -742,23 +742,23 @@ void tx_rf(RU_t *ru) {
|
||||
flags = 4; // start of burst and end of burst (only one DL SF between two UL)
|
||||
sf_extension = ru->N_TA_offset<<1;
|
||||
} */
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, proc->tti_tx );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot );
|
||||
|
||||
for (i=0; i<ru->nb_tx; i++)
|
||||
txp[i] = (void *)&ru->common.txdata[i][(proc->tti_tx*fp->samples_per_slot)-sf_extension];
|
||||
txp[i] = (void *)&ru->common.txdata[i][(slot*fp->samples_per_slot)-sf_extension];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-ru->openair0_cfg.tx_sample_advance)&0xffffffff );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff );
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
|
||||
// prepare tx buffer pointers
|
||||
txs = ru->rfdevice.trx_write_func(&ru->rfdevice,
|
||||
proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
|
||||
timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
|
||||
txp,
|
||||
siglen+sf_extension,
|
||||
ru->nb_tx,
|
||||
flags);
|
||||
LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx,
|
||||
(long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->tti_tx);
|
||||
(long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
|
||||
AssertFatal(txs == siglen+sf_extension,"TX : Timeout (sent %d/%d)\n",txs, siglen);
|
||||
}
|
||||
@@ -1206,36 +1206,40 @@ static void *ru_thread_tx( void *param ) {
|
||||
char filename[40];
|
||||
int print_frame = 8;
|
||||
int i = 0;
|
||||
cpu_set_t cpuset;
|
||||
CPU_ZERO(&cpuset);
|
||||
//CPU_SET(5, &cpuset);
|
||||
//pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
|
||||
//wait_sync("ru_thread_tx");
|
||||
int ret;
|
||||
|
||||
|
||||
wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx");
|
||||
printf( "ru_thread_tx ready\n");
|
||||
|
||||
while (!oai_exit) {
|
||||
if (oai_exit) break;
|
||||
|
||||
LOG_I(PHY,"ru_thread_tx: Waiting for TX processing\n");
|
||||
LOG_D(PHY,"ru_thread_tx: Waiting for TX processing\n");
|
||||
// wait until eNBs are finished subframe RX n and TX n+4
|
||||
wait_on_condition(&proc->mutex_gNBs,&proc->cond_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx");
|
||||
|
||||
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_gNBs))==0,"mutex_lock return %d\n",ret);
|
||||
int frame_tx=proc->frame_tx;
|
||||
int tti_tx =proc->tti_tx;
|
||||
uint64_t timestamp_tx = proc->timestamp_tx;
|
||||
|
||||
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_gNBs))==0,"mutex_lock returns %d\n",ret);
|
||||
|
||||
if (oai_exit) break;
|
||||
|
||||
//printf("~~~~~~~~~~~~~~~~start process for ru_thread_tx %d.%d\n", proc->frame_tx, proc->tti_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, proc->tti_tx );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, tti_tx );
|
||||
|
||||
// do TX front-end processing if needed (precoding and/or IDFTs)
|
||||
if (ru->feptx_prec) ru->feptx_prec(ru);
|
||||
if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx);
|
||||
|
||||
// do OFDM if needed
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru);
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_tx);
|
||||
|
||||
if(!emulate_rf) {
|
||||
// do outgoing fronthaul (south) if needed
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru);
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,tti_tx,timestamp_tx);
|
||||
|
||||
if (ru->fh_north_out) ru->fh_north_out(ru);
|
||||
} else {
|
||||
@@ -1265,12 +1269,13 @@ static void *ru_thread_tx( void *param ) {
|
||||
}//else emulate_rf
|
||||
|
||||
release_thread(&proc->mutex_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx");
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, proc->instance_cnt_gNBs);
|
||||
|
||||
for(i = 0; i<ru->num_gNB; i++) {
|
||||
gNB = ru->gNB_list[i];
|
||||
gNB_proc = &gNB->proc;
|
||||
L1_proc = (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)? &gNB_proc->L1_proc_tx : &gNB_proc->L1_proc;
|
||||
pthread_mutex_lock(&gNB_proc->mutex_RU_tx);
|
||||
AssertFatal((ret=pthread_mutex_lock(&gNB_proc->mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
|
||||
|
||||
for (int j=0; j<gNB->num_RU; j++) {
|
||||
if (ru == gNB->RU_list[j]) {
|
||||
@@ -1283,20 +1288,21 @@ static void *ru_thread_tx( void *param ) {
|
||||
}
|
||||
|
||||
if (gNB_proc->RU_mask_tx != (1<<gNB->num_RU)-1) { // not all RUs have provided their information so return
|
||||
pthread_mutex_unlock(&gNB_proc->mutex_RU_tx);
|
||||
} else { // all RUs TX are finished so send the ready signal to eNB processing
|
||||
AssertFatal((ret=pthread_mutex_unlock(&gNB_proc->mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
} else { // all RUs TX are finished so send the ready signal to gNB processing
|
||||
gNB_proc->RU_mask_tx = 0;
|
||||
pthread_mutex_unlock(&gNB_proc->mutex_RU_tx);
|
||||
pthread_mutex_lock( &L1_proc->mutex_RUs);
|
||||
L1_proc->instance_cnt_RUs = 0;
|
||||
AssertFatal((ret=pthread_mutex_unlock(&gNB_proc->mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
|
||||
AssertFatal((ret=pthread_mutex_lock(&L1_proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret);
|
||||
// the thread can now be woken up
|
||||
if (pthread_cond_signal(&L1_proc->cond_RUs) != 0) {
|
||||
LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
|
||||
exit_fun( "ERROR pthread_cond_signal" );
|
||||
}
|
||||
if (L1_proc->instance_cnt_RUs==-1) {
|
||||
AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0,
|
||||
"ERROR pthread_cond_signal for gNB_L1_thread\n");
|
||||
} //else AssertFatal(1==0,"gNB TX thread is not ready\n");
|
||||
L1_proc->instance_cnt_RUs = 0;
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs);
|
||||
AssertFatal((ret=pthread_mutex_unlock(&L1_proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
|
||||
pthread_mutex_unlock( &L1_proc->mutex_RUs );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1320,6 +1326,8 @@ static void *ru_thread( void *param ) {
|
||||
ru_thread_status = 0;
|
||||
// set default return value
|
||||
sprintf(threadname,"ru_thread %d",ru->idx);
|
||||
|
||||
|
||||
LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]);
|
||||
|
||||
if(emulate_rf) {
|
||||
@@ -1430,23 +1438,23 @@ static void *ru_thread( void *param ) {
|
||||
if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023;
|
||||
|
||||
// do RX front-end processing (frequency-shift, dft) if needed
|
||||
if (ru->feprx) ru->feprx(ru);
|
||||
if (ru->feprx) ru->feprx(ru,proc->tti_rx);
|
||||
|
||||
// At this point, all information for subframe has been received on FH interface
|
||||
|
||||
// wakeup all gNB processes waiting for this RU
|
||||
if (ru->num_gNB>0) wakeup_gNB_L1s(ru);
|
||||
|
||||
if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD && ru->num_eNB==0) {
|
||||
if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD && ru->num_gNB==0) {
|
||||
// do TX front-end processing if needed (precoding and/or IDFTs)
|
||||
if (ru->feptx_prec) ru->feptx_prec(ru);
|
||||
if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx);
|
||||
|
||||
// do OFDM if needed
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru);
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx);
|
||||
|
||||
if(!emulate_rf) {
|
||||
// do outgoing fronthaul (south) if needed
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru);
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx);
|
||||
|
||||
if (ru->fh_north_out) ru->fh_north_out(ru);
|
||||
} else {
|
||||
@@ -1580,11 +1588,11 @@ int stop_rf(RU_t *ru) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void fep_full(RU_t *ru);
|
||||
extern void ru_fep_full_2thread(RU_t *ru);
|
||||
extern void nr_feptx_ofdm(RU_t *ru);
|
||||
extern void nr_feptx_ofdm_2thread(RU_t *ru);
|
||||
extern void feptx_prec(RU_t *ru);
|
||||
extern void fep_full(RU_t *ru,int slot);
|
||||
extern void ru_fep_full_2thread(RU_t *ru,int slot);
|
||||
extern void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx);
|
||||
extern void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx);
|
||||
extern void feptx_prec(RU_t *ru, int frame_tx,int tti_tx);
|
||||
extern void init_fep_thread(RU_t *ru);
|
||||
extern void init_nr_feptx_thread(RU_t *ru);
|
||||
|
||||
|
||||
@@ -381,13 +381,14 @@ void reset_stats(FL_OBJECT *button, long arg) {
|
||||
phy_vars_gNB->UE_stats[i].dlsch_NAK[k][j]=0;
|
||||
phy_vars_gNB->UE_stats[i].dlsch_ACK[k][j]=0;
|
||||
phy_vars_gNB->UE_stats[i].dlsch_trials[k][j]=0;
|
||||
}*/
|
||||
}
|
||||
phy_vars_gNB->UE_stats[i].dlsch_l2_errors[k]=0;
|
||||
phy_vars_gNB->UE_stats[i].ulsch_errors[k]=0;
|
||||
phy_vars_gNB->UE_stats[i].ulsch_consecutive_errors=0;
|
||||
phy_vars_gNB->UE_stats[i].dlsch_sliding_cnt=0;
|
||||
phy_vars_gNB->UE_stats[i].dlsch_NAK_round0=0;
|
||||
phy_vars_gNB->UE_stats[i].dlsch_mcs_offset=0;
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-6
@@ -169,6 +169,7 @@ static void UE_synch(void *arg) {
|
||||
int freq_offset=0;
|
||||
UE->is_synchronized = 0;
|
||||
|
||||
|
||||
if (UE->UE_scan == 0) {
|
||||
get_band(downlink_frequency[CC_id][0], &UE->frame_parms.eutra_band, &uplink_frequency_offset[CC_id][0], &UE->frame_parms.frame_type);
|
||||
LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n",
|
||||
@@ -239,7 +240,7 @@ static void UE_synch(void *arg) {
|
||||
case pbch:
|
||||
LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
|
||||
|
||||
if (nr_initial_sync( &syncD->proc, UE, UE->mode ) == 0) {
|
||||
if (nr_initial_sync( &syncD->proc, UE, UE->mode,2) == 0) {
|
||||
freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
|
||||
hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_slot;
|
||||
LOG_I(PHY,"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
|
||||
@@ -348,7 +349,7 @@ static void UE_synch(void *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
void processSubframeRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
|
||||
void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
|
||||
// Process Rx data for one sub-frame
|
||||
if (slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx) & NR_DOWNLINK_SLOT) {
|
||||
//clean previous FAPI MESSAGE
|
||||
@@ -376,9 +377,9 @@ void processSubframeRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
|
||||
phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
|
||||
#else
|
||||
uint64_t a=rdtsc();
|
||||
phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode);
|
||||
phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode, UE_mac->phy_config.config_req.pbch_config);
|
||||
LOG_D(PHY,"phy_procedures_nrUE_RX: slot:%d, time %lu\n", proc->nr_tti_rx, (rdtsc()-a)/3500);
|
||||
// printf(">>> nr_ue_pdcch_procedures ended\n");
|
||||
//printf(">>> nr_ue_pdcch_procedures ended\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -413,7 +414,7 @@ void UE_processing(void *arg) {
|
||||
processingData_t *rxtxD=(processingData_t *) arg;
|
||||
UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
|
||||
PHY_VARS_NR_UE *UE = rxtxD->UE;
|
||||
processSubframeRX(UE, proc);
|
||||
processSlotRX(UE, proc);
|
||||
//printf(">>> mac ended\n");
|
||||
// Prepare the future Tx data
|
||||
#if 0
|
||||
@@ -447,7 +448,7 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4);
|
||||
|
||||
for(int x=0; x<10; x++) {
|
||||
for(int x=0; x<20; x++) { // two frames for initial sync
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
rxp[i] = ((void *)&UE->common_vars.rxdata[i][0]) + 4*x*UE->frame_parms.samples_per_subframe;
|
||||
|
||||
@@ -613,6 +614,7 @@ void *UE_thread(void *arg) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
absolute_slot++;
|
||||
// whatever means thread_idx
|
||||
// Fix me: will be wrong when slot 1 is slow, as slot 2 finishes
|
||||
|
||||
@@ -393,7 +393,7 @@ static void get_options(void) {
|
||||
uint32_t online_log_messages;
|
||||
uint32_t glog_level, glog_verbosity;
|
||||
uint32_t start_telnetsrv=0;
|
||||
paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
|
||||
paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC_UE ;
|
||||
paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
|
||||
config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL);
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
/* command line parameters common to eNodeB and UE */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define CMDLINE_PARAMS_DESC { \
|
||||
#define CMDLINE_PARAMS_DESC_UE { \
|
||||
{"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&rf_config_file, defstrval:NULL, TYPE_STRING, sizeof(rf_config_file)}, \
|
||||
{"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \
|
||||
{"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&phy_test, defintval:0, TYPE_INT, 0}, \
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
#define NUMBER_OF_NR_RU_MAX 2
|
||||
#ifndef PHYSIM
|
||||
#ifndef UE_EXPANSION
|
||||
#define NUMBER_OF_UE_MAX 4
|
||||
#define NUMBER_OF_NR_UE_MAX 4
|
||||
#define NUMBER_OF_CONNECTED_eNB_MAX 1
|
||||
#define NUMBER_OF_CONNECTED_gNB_MAX 1
|
||||
#define NUMBER_OF_UE_MAX 16
|
||||
#define NUMBER_OF_NR_UE_MAX 16
|
||||
#define NUMBER_OF_CONNECTED_eNB_MAX 3
|
||||
#define NUMBER_OF_CONNECTED_gNB_MAX 3
|
||||
#else
|
||||
#define NUMBER_OF_UE_MAX 256
|
||||
#define NUMBER_OF_NR_UE_MAX 256
|
||||
|
||||
Reference in New Issue
Block a user