Commit e64af659 authored by Raymond Knopp's avatar Raymond Knopp

testing of low-level parallelization of FEP in eNodeB RX.

parent f52cbeeb
......@@ -246,6 +246,8 @@ typedef struct eNB_proc_t_s {
int frame_rx;
/// frame to act upon for PRACH
int frame_prach;
/// \internal This variable is protected by \ref mutex_fep.
int instance_cnt_fep;
/// \brief Instance count for FH processing thread.
/// \internal This variable is protected by \ref mutex_FH.
int instance_cnt_FH;
......@@ -264,6 +266,8 @@ typedef struct eNB_proc_t_s {
int first_rx;
/// flag to indicate first TX transmission
int first_tx;
/// pthread attributes for parallel fep thread
pthread_attr_t attr_fep;
/// pthread attributes for FH processing thread
pthread_attr_t attr_FH;
/// pthread attributes for single eNB processing thread
......@@ -272,6 +276,8 @@ typedef struct eNB_proc_t_s {
pthread_attr_t attr_prach;
/// pthread attributes for asynchronous RX thread
pthread_attr_t attr_asynch_rxtx;
/// scheduling parameters for parallel fep thread
struct sched_param sched_param_fep;
/// scheduling parameters for FH thread
struct sched_param sched_param_FH;
/// scheduling parameters for single eNB thread
......@@ -280,14 +286,20 @@ typedef struct eNB_proc_t_s {
struct sched_param sched_param_prach;
/// scheduling parameters for asynch_rxtx thread
struct sched_param sched_param_asynch_rxtx;
/// pthread structure for parallel fep thread
pthread_t pthread_fep;
/// pthread structure for PRACH thread
pthread_t pthread_prach;
/// condition variable for parallel fep thread
pthread_cond_t cond_fep;
/// condition variable for FH thread
pthread_cond_t cond_FH;
/// condition variable for PRACH processing thread;
pthread_cond_t cond_prach;
/// condition variable for asynch RX/TX thread
pthread_cond_t cond_asynch_rxtx;
/// mutex for parallel fep thread
pthread_mutex_t mutex_fep;
/// mutex for FH
pthread_mutex_t mutex_FH;
/// 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) {
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_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) {
......@@ -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_2thread(PHY_VARS_eNB *eNB);
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);
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)
for (i=0; i<2; i++) {
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;
phy_procedures_eNB_common_RX(eNB);
......@@ -1700,6 +1705,9 @@ int main(int argc, char **argv)
}//ch realization
oai_exit=1;
pthread_cond_signal(&eNB->proc.cond_fep);
if (abstx) { // ABSTRACTION
fprintf(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) {
......@@ -1337,7 +1338,7 @@ void init_eNB_proc(int inst) {
PHY_VARS_eNB *eNB;
eNB_proc_t *proc;
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++) {
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[0].instance_cnt_rxtx = -1;
proc_rxtx[1].instance_cnt_rxtx = -1;
proc->instance_cnt_prach = -1;
proc->instance_cnt_FH = -1;
proc->instance_cnt_prach = -1;
proc->instance_cnt_FH = -1;
proc->instance_cnt_asynch_rxtx = -1;
proc->CC_id = CC_id;
proc->CC_id = CC_id;
proc->first_rx=1;
proc->first_tx=1;
......@@ -1373,6 +1374,7 @@ void init_eNB_proc(int inst) {
attr_prach = &proc->attr_prach;
attr_asynch = &proc->attr_asynch_rxtx;
attr_single = &proc->attr_single;
attr_fep = &proc->attr_fep;
#endif
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->pthread_FH, attr_FH, eNB_thread_FH, &eNB->proc );
}
else
else {
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 );
if ((eNB->node_timing == synch_to_other) ||
(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;
case NGFI_RRU_IF4p5:
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_tx = NULL;//proc_tx_rru_if4p5;
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;
case eNodeB_3GPP:
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_tx = proc_tx_full;
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;
case eNodeB_3GPP_BBU:
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_tx = proc_tx_full;
eNB->tx_fh = tx_fh_if5;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment