testing of low-level parallelization of FEP in eNodeB RX.
This commit is contained in:
@@ -246,6 +246,8 @@ typedef struct eNB_proc_t_s {
|
|||||||
int frame_rx;
|
int frame_rx;
|
||||||
/// frame to act upon for PRACH
|
/// frame to act upon for PRACH
|
||||||
int frame_prach;
|
int frame_prach;
|
||||||
|
/// \internal This variable is protected by \ref mutex_fep.
|
||||||
|
int instance_cnt_fep;
|
||||||
/// \brief Instance count for FH processing thread.
|
/// \brief Instance count for FH processing thread.
|
||||||
/// \internal This variable is protected by \ref mutex_FH.
|
/// \internal This variable is protected by \ref mutex_FH.
|
||||||
int instance_cnt_FH;
|
int instance_cnt_FH;
|
||||||
@@ -264,6 +266,8 @@ typedef struct eNB_proc_t_s {
|
|||||||
int first_rx;
|
int first_rx;
|
||||||
/// flag to indicate first TX transmission
|
/// flag to indicate first TX transmission
|
||||||
int first_tx;
|
int first_tx;
|
||||||
|
/// pthread attributes for parallel fep thread
|
||||||
|
pthread_attr_t attr_fep;
|
||||||
/// pthread attributes for FH processing thread
|
/// pthread attributes for FH processing thread
|
||||||
pthread_attr_t attr_FH;
|
pthread_attr_t attr_FH;
|
||||||
/// pthread attributes for single eNB processing thread
|
/// pthread attributes for single eNB processing thread
|
||||||
@@ -272,6 +276,8 @@ typedef struct eNB_proc_t_s {
|
|||||||
pthread_attr_t attr_prach;
|
pthread_attr_t attr_prach;
|
||||||
/// pthread attributes for asynchronous RX thread
|
/// pthread attributes for asynchronous RX thread
|
||||||
pthread_attr_t attr_asynch_rxtx;
|
pthread_attr_t attr_asynch_rxtx;
|
||||||
|
/// scheduling parameters for parallel fep thread
|
||||||
|
struct sched_param sched_param_fep;
|
||||||
/// scheduling parameters for FH thread
|
/// scheduling parameters for FH thread
|
||||||
struct sched_param sched_param_FH;
|
struct sched_param sched_param_FH;
|
||||||
/// scheduling parameters for single eNB thread
|
/// scheduling parameters for single eNB thread
|
||||||
@@ -280,14 +286,20 @@ typedef struct eNB_proc_t_s {
|
|||||||
struct sched_param sched_param_prach;
|
struct sched_param sched_param_prach;
|
||||||
/// scheduling parameters for asynch_rxtx thread
|
/// scheduling parameters for asynch_rxtx thread
|
||||||
struct sched_param sched_param_asynch_rxtx;
|
struct sched_param sched_param_asynch_rxtx;
|
||||||
|
/// pthread structure for parallel fep thread
|
||||||
|
pthread_t pthread_fep;
|
||||||
/// pthread structure for PRACH thread
|
/// pthread structure for PRACH thread
|
||||||
pthread_t pthread_prach;
|
pthread_t pthread_prach;
|
||||||
|
/// condition variable for parallel fep thread
|
||||||
|
pthread_cond_t cond_fep;
|
||||||
/// condition variable for FH thread
|
/// condition variable for FH thread
|
||||||
pthread_cond_t cond_FH;
|
pthread_cond_t cond_FH;
|
||||||
/// condition variable for PRACH processing thread;
|
/// condition variable for PRACH processing thread;
|
||||||
pthread_cond_t cond_prach;
|
pthread_cond_t cond_prach;
|
||||||
/// condition variable for asynch RX/TX thread
|
/// condition variable for asynch RX/TX thread
|
||||||
pthread_cond_t cond_asynch_rxtx;
|
pthread_cond_t cond_asynch_rxtx;
|
||||||
|
/// mutex for parallel fep thread
|
||||||
|
pthread_mutex_t mutex_fep;
|
||||||
/// mutex for FH
|
/// mutex for FH
|
||||||
pthread_mutex_t mutex_FH;
|
pthread_mutex_t mutex_FH;
|
||||||
/// mutex for PRACH thread
|
/// mutex for PRACH thread
|
||||||
|
|||||||
@@ -2497,6 +2497,158 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PHY_VARS_eNB *eNB;
|
||||||
|
int slot;
|
||||||
|
} fep_task;
|
||||||
|
|
||||||
|
void fep0(PHY_VARS_eNB *eNB,int slot) {
|
||||||
|
|
||||||
|
eNB_proc_t *proc = &eNB->proc;
|
||||||
|
LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
|
||||||
|
int l;
|
||||||
|
|
||||||
|
remove_7_5_kHz(eNB,(slot&1)+(proc->subframe_rx<<1));
|
||||||
|
for (l=0; l<fp->symbols_per_tti/2; l++) {
|
||||||
|
slot_fep_ul(fp,
|
||||||
|
&eNB->common_vars,
|
||||||
|
l,
|
||||||
|
(slot&1)+(proc->subframe_rx<<1),
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) {
|
||||||
|
|
||||||
|
if (pthread_mutex_lock(mutex) != 0) {
|
||||||
|
LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
|
||||||
|
exit_fun("nothing to add");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
*instance_cnt=*instance_cnt-1;
|
||||||
|
|
||||||
|
if (pthread_mutex_unlock(mutex) != 0) {
|
||||||
|
LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for %s\n",name);
|
||||||
|
exit_fun("nothing to add");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
|
||||||
|
|
||||||
|
if (pthread_mutex_lock(mutex) != 0) {
|
||||||
|
LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
|
||||||
|
exit_fun("nothing to add");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*instance_cnt < 0) {
|
||||||
|
// most of the time the thread is waiting here
|
||||||
|
// proc->instance_cnt_rxtx is -1
|
||||||
|
pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_mutex_unlock(mutex) != 0) {
|
||||||
|
LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name);
|
||||||
|
exit_fun("nothing to add");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int oai_exit;
|
||||||
|
|
||||||
|
|
||||||
|
static void *fep_thread(void *param) {
|
||||||
|
|
||||||
|
PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param;
|
||||||
|
eNB_proc_t *proc = &eNB->proc;
|
||||||
|
while (!oai_exit) {
|
||||||
|
printf("Waiting for parallel FEP signal\n");
|
||||||
|
if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread")<0) break;
|
||||||
|
printf("Running parallel FEP on first slot\n");
|
||||||
|
fep0(eNB,0);
|
||||||
|
if (release_thread(&proc->mutex_fep,&proc->instance_cnt_fep,"fep thread")<0) break;
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_fep_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_fep) {
|
||||||
|
|
||||||
|
eNB_proc_t *proc = &eNB->proc;
|
||||||
|
|
||||||
|
proc->instance_cnt_fep = -1;
|
||||||
|
|
||||||
|
pthread_mutex_init( &proc->mutex_fep, NULL);
|
||||||
|
pthread_cond_init( &proc->cond_fep, NULL);
|
||||||
|
|
||||||
|
pthread_create(&proc->pthread_fep, attr_fep, fep_thread, (void*)eNB);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) {
|
||||||
|
|
||||||
|
eNB_proc_t *proc = &eNB->proc;
|
||||||
|
struct timespec wait;
|
||||||
|
int wait_cnt=0;
|
||||||
|
wait.tv_sec=0;
|
||||||
|
wait.tv_nsec=5000000L;
|
||||||
|
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
|
||||||
|
start_meas(&eNB->ofdm_demod_stats);
|
||||||
|
|
||||||
|
printf("Running 2 thread FEP\n");
|
||||||
|
|
||||||
|
if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) {
|
||||||
|
printf("[eNB] ERROR pthread_mutex_lock for fep thread %d (IC %d)\n", proc->instance_cnt_fep);
|
||||||
|
exit_fun( "error locking mutex_fep" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proc->instance_cnt_fep==0) {
|
||||||
|
printf("[eNB] FEP thread busy\n");
|
||||||
|
exit_fun("FEP thread busy");
|
||||||
|
pthread_mutex_unlock( &proc->mutex_fep );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
++proc->instance_cnt_fep;
|
||||||
|
|
||||||
|
printf("[eNB] waking up FEP thread\n");
|
||||||
|
if (pthread_cond_signal(&proc->cond_fep) != 0) {
|
||||||
|
printf("[eNB] ERROR pthread_cond_signal for fep thread\n");
|
||||||
|
exit_fun( "ERROR pthread_cond_signal" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock( &proc->mutex_fep );
|
||||||
|
|
||||||
|
// call second slot in this symbol
|
||||||
|
printf("Calling FEP for 2nd slot\n");
|
||||||
|
fep0(eNB,1);
|
||||||
|
|
||||||
|
if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) {
|
||||||
|
printf("[eNB] ERROR pthread_mutex_lock for fep thread %d (IC %d)\n", proc->instance_cnt_fep);
|
||||||
|
exit_fun( "error locking mutex_fep" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (proc->instance_cnt_fep==0) {
|
||||||
|
wait_cnt++;
|
||||||
|
if (wait_cnt>10000)
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
pthread_mutex_unlock( &proc->mutex_fep );
|
||||||
|
if (wait_cnt>10000) {
|
||||||
|
printf("[eNB] parallel FEP didn't finish\n");
|
||||||
|
exit_fun( "error" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void eNB_fep_full(PHY_VARS_eNB *eNB) {
|
void eNB_fep_full(PHY_VARS_eNB *eNB) {
|
||||||
|
|
||||||
eNB_proc_t *proc = &eNB->proc;
|
eNB_proc_t *proc = &eNB->proc;
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ double t_rx_min = 1000000000; /*!< \brief initial min process time for tx */
|
|||||||
int n_tx_dropped = 0; /*!< \brief initial max process time for tx */
|
int n_tx_dropped = 0; /*!< \brief initial max process time for tx */
|
||||||
int n_rx_dropped = 0; /*!< \brief initial max process time for rx */
|
int n_rx_dropped = 0; /*!< \brief initial max process time for rx */
|
||||||
|
|
||||||
|
int oai_exit = 0;
|
||||||
|
|
||||||
|
|
||||||
void fill_ulsch_dci(PHY_VARS_eNB *eNB,void *UL_dci,int first_rb,int nb_rb,int mcs,int ndi,int cqi_flag) {
|
void fill_ulsch_dci(PHY_VARS_eNB *eNB,void *UL_dci,int first_rb,int nb_rb,int mcs,int ndi,int cqi_flag) {
|
||||||
|
|
||||||
@@ -171,6 +173,7 @@ void fill_ulsch_dci(PHY_VARS_eNB *eNB,void *UL_dci,int first_rb,int nb_rb,int mc
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern void eNB_fep_full(PHY_VARS_eNB *eNB);
|
extern void eNB_fep_full(PHY_VARS_eNB *eNB);
|
||||||
|
extern void eNB_fep_full_2thread(PHY_VARS_eNB *eNB);
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -688,6 +691,8 @@ int main(int argc, char **argv)
|
|||||||
eNB->ulsch[0] = new_eNB_ulsch(max_turbo_iterations,N_RB_DL,0);
|
eNB->ulsch[0] = new_eNB_ulsch(max_turbo_iterations,N_RB_DL,0);
|
||||||
UE->ulsch[0] = new_ue_ulsch(N_RB_DL,0);
|
UE->ulsch[0] = new_ue_ulsch(N_RB_DL,0);
|
||||||
|
|
||||||
|
init_fep_thread(eNB,&eNB->proc.attr_fep);
|
||||||
|
|
||||||
// Create transport channel structures for 2 transport blocks (MIMO)
|
// Create transport channel structures for 2 transport blocks (MIMO)
|
||||||
for (i=0; i<2; i++) {
|
for (i=0; i<2; i++) {
|
||||||
eNB->dlsch[0][i] = new_eNB_dlsch(1,8,1827072,N_RB_DL,0);
|
eNB->dlsch[0][i] = new_eNB_dlsch(1,8,1827072,N_RB_DL,0);
|
||||||
@@ -1181,7 +1186,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
eNB->fep = eNB_fep_full;
|
eNB->fep = eNB_fep_full_2thread;
|
||||||
eNB->do_prach = NULL;
|
eNB->do_prach = NULL;
|
||||||
|
|
||||||
phy_procedures_eNB_common_RX(eNB);
|
phy_procedures_eNB_common_RX(eNB);
|
||||||
@@ -1700,6 +1705,9 @@ int main(int argc, char **argv)
|
|||||||
}//ch realization
|
}//ch realization
|
||||||
|
|
||||||
|
|
||||||
|
oai_exit=1;
|
||||||
|
pthread_cond_signal(&eNB->proc.cond_fep);
|
||||||
|
|
||||||
if (abstx) { // ABSTRACTION
|
if (abstx) { // ABSTRACTION
|
||||||
fprintf(csv_fdUL,"];");
|
fprintf(csv_fdUL,"];");
|
||||||
fclose(csv_fdUL);
|
fclose(csv_fdUL);
|
||||||
|
|||||||
@@ -1329,6 +1329,7 @@ static void* eNB_thread_single( void* param ) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *);
|
||||||
|
|
||||||
void init_eNB_proc(int inst) {
|
void init_eNB_proc(int inst) {
|
||||||
|
|
||||||
@@ -1337,7 +1338,7 @@ void init_eNB_proc(int inst) {
|
|||||||
PHY_VARS_eNB *eNB;
|
PHY_VARS_eNB *eNB;
|
||||||
eNB_proc_t *proc;
|
eNB_proc_t *proc;
|
||||||
eNB_rxtx_proc_t *proc_rxtx;
|
eNB_rxtx_proc_t *proc_rxtx;
|
||||||
pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL;
|
pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL;
|
||||||
|
|
||||||
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||||
eNB = PHY_vars_eNB_g[inst][CC_id];
|
eNB = PHY_vars_eNB_g[inst][CC_id];
|
||||||
@@ -1347,10 +1348,10 @@ void init_eNB_proc(int inst) {
|
|||||||
proc_rxtx = proc->proc_rxtx;
|
proc_rxtx = proc->proc_rxtx;
|
||||||
proc_rxtx[0].instance_cnt_rxtx = -1;
|
proc_rxtx[0].instance_cnt_rxtx = -1;
|
||||||
proc_rxtx[1].instance_cnt_rxtx = -1;
|
proc_rxtx[1].instance_cnt_rxtx = -1;
|
||||||
proc->instance_cnt_prach = -1;
|
proc->instance_cnt_prach = -1;
|
||||||
proc->instance_cnt_FH = -1;
|
proc->instance_cnt_FH = -1;
|
||||||
proc->instance_cnt_asynch_rxtx = -1;
|
proc->instance_cnt_asynch_rxtx = -1;
|
||||||
proc->CC_id = CC_id;
|
proc->CC_id = CC_id;
|
||||||
|
|
||||||
proc->first_rx=1;
|
proc->first_rx=1;
|
||||||
proc->first_tx=1;
|
proc->first_tx=1;
|
||||||
@@ -1373,6 +1374,7 @@ void init_eNB_proc(int inst) {
|
|||||||
attr_prach = &proc->attr_prach;
|
attr_prach = &proc->attr_prach;
|
||||||
attr_asynch = &proc->attr_asynch_rxtx;
|
attr_asynch = &proc->attr_asynch_rxtx;
|
||||||
attr_single = &proc->attr_single;
|
attr_single = &proc->attr_single;
|
||||||
|
attr_fep = &proc->attr_fep;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (eNB->single_thread_flag==0) {
|
if (eNB->single_thread_flag==0) {
|
||||||
@@ -1380,9 +1382,10 @@ void init_eNB_proc(int inst) {
|
|||||||
pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] );
|
pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] );
|
||||||
pthread_create( &proc->pthread_FH, attr_FH, eNB_thread_FH, &eNB->proc );
|
pthread_create( &proc->pthread_FH, attr_FH, eNB_thread_FH, &eNB->proc );
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
pthread_create(&proc->pthread_single, attr_single, eNB_thread_single, &eNB->proc);
|
pthread_create(&proc->pthread_single, attr_single, eNB_thread_single, &eNB->proc);
|
||||||
|
init_fep_thread(eNB,attr_fep);
|
||||||
|
}
|
||||||
pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, &eNB->proc );
|
pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, &eNB->proc );
|
||||||
if ((eNB->node_timing == synch_to_other) ||
|
if ((eNB->node_timing == synch_to_other) ||
|
||||||
(eNB->node_function == NGFI_RRU_IF5) ||
|
(eNB->node_function == NGFI_RRU_IF5) ||
|
||||||
@@ -1631,7 +1634,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
|
|||||||
break;
|
break;
|
||||||
case NGFI_RRU_IF4p5:
|
case NGFI_RRU_IF4p5:
|
||||||
eNB->do_prach = do_prach;
|
eNB->do_prach = do_prach;
|
||||||
eNB->fep = eNB_fep_full;
|
eNB->fep = (eNB->single_thread_flag == 0) ? NB_fep_full : eNB_fep_full_2thread;
|
||||||
eNB->proc_uespec_rx = NULL;
|
eNB->proc_uespec_rx = NULL;
|
||||||
eNB->proc_tx = NULL;//proc_tx_rru_if4p5;
|
eNB->proc_tx = NULL;//proc_tx_rru_if4p5;
|
||||||
eNB->tx_fh = NULL;
|
eNB->tx_fh = NULL;
|
||||||
@@ -1658,7 +1661,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
|
|||||||
break;
|
break;
|
||||||
case eNodeB_3GPP:
|
case eNodeB_3GPP:
|
||||||
eNB->do_prach = do_prach;
|
eNB->do_prach = do_prach;
|
||||||
eNB->fep = eNB_fep_full;
|
eNB->fep = (eNB->single_thread_flag == 0) ? NB_fep_full : eNB_fep_full_2thread;
|
||||||
eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX;
|
eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX;
|
||||||
eNB->proc_tx = proc_tx_full;
|
eNB->proc_tx = proc_tx_full;
|
||||||
eNB->tx_fh = NULL;
|
eNB->tx_fh = NULL;
|
||||||
@@ -1676,7 +1679,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
|
|||||||
break;
|
break;
|
||||||
case eNodeB_3GPP_BBU:
|
case eNodeB_3GPP_BBU:
|
||||||
eNB->do_prach = do_prach;
|
eNB->do_prach = do_prach;
|
||||||
eNB->fep = eNB_fep_full;
|
eNB->fep = (eNB->single_thread_flag == 0) ? NB_fep_full : eNB_fep_full_2thread;
|
||||||
eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX;
|
eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX;
|
||||||
eNB->proc_tx = proc_tx_full;
|
eNB->proc_tx = proc_tx_full;
|
||||||
eNB->tx_fh = tx_fh_if5;
|
eNB->tx_fh = tx_fh_if5;
|
||||||
|
|||||||
Reference in New Issue
Block a user