Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pasolini/openairinterface5g
  • odukan/openairinterface5g
  • ewa/openairinterface5g
  • deksprime/openairinterface5g
  • jackokie/openairinterface5g
  • Srushti16/openairinterface5g
  • BRodolphe/openairinterface5g
  • kramantas/openairinterface5g
  • suraj_4g5g/openairinterface5g
  • turletti/openairinterface5g
  • anandriisc/openairinterface5g
  • lvguorong/openairinterface5g
  • dast/openairinterface5g
  • yashwanthr/openairinterface5g
  • ajiti2tb/openairinterface5g
  • qzhou/openairinterface5g
  • nickmxxx/openairinterface5g
  • bin_he4/openairinterface5g
  • delarco/openairinterface5g
  • limx1980/openairinterface5g
  • Aniq/openairinterface5g
  • yassir63/openairinterface5g
  • orc318/openairinterface5g
  • vader/openairinterface5g
  • limx59/openairinterface5g
  • nadavaati_12345/openairinterface5g
  • jenshz/openairinterface5g
  • kuldeep/openairinterface5g
  • lurker/openairinterface5g
  • shariat/openairinterface5g
  • Alireza.najafzadeh/openairinterface5g
  • Ling/openairinterface5g
  • EvanKrall/openairinterface5g
  • youyih/openairinterface5g
  • anindya/openairinterface5g
  • ahan/openairinterface5g
  • beraoud/openairinterface5g
  • obejarano/openairinterface5g
  • Monti/openairinterface5g
  • akhamsi/openairinterface5g
  • Worker.N/openairinterface5g
  • zhangtu/openairinterface5g
  • desouza/openairinterface5g
  • zhijun/openairinterface5g
  • sureshkumar/openairinterface5g
  • milan/openairinterface5g
  • bigbangbingo/openairinterface5g
  • platini/openairinterface5g
  • muralir-nv/openairinterface5g
  • Joshua_Zhang/openairinterface5g
  • siddharthmurali1/openairinterface5g
  • sorinros/openairinterface5g
  • elainecao/openairinterface5g
  • sneltved/openairinterface5g
  • aikaterini.trilyraki/openairinterface5g
  • wujunning11/openairinterface5g
  • magounak/openairinterface5g
  • ycl1729020039/openairinterface5g
  • mayukhweb/openairinterface5g
  • wataru/openairinterface5g
  • afonsoli/openairinterface5g
  • ppokar/openairinterface5g
  • emest/openairinterface5g
  • Najib/openairinterface5g
  • liqing/openairinterface5g
  • gprshome/openairinterface5g
  • Dvevgedveccc/openairinterface5g
  • Elena_Lukashova/openairinterface5g
  • imaneouss/openairinterface5g
  • yangyuan/openairinterface5g
  • ycliang/openairinterface5g
  • rohanfds/openairinterface5g
  • cong2008abc/openairinterface5g
  • Giovanni/openairinterface5g
  • willvegapunk/openairinterface5g
  • Chen/openairinterface5g
  • Ella/openairinterface5g
  • kollabalu/openairinterface5g
  • tsaichanglan/openairinterface5g
  • Artifice/openairinterface5g
  • HJR0129/openairinterface5g
  • alextp/openairinterface5g
  • Changron/openairinterface5g
  • pedosb/openairinterface5g
  • Flozzen/openairinterface5g
  • hobei/openairinterface5g
  • WP_Jing/openairinterface5g
  • reset4/openairinterface5g
  • alexjoseph/openairinterface5g
  • latuan1710/openairinterface5g
  • wynter-wang/openairinterface5g
  • stt12706/openairinterface5g
  • sy/openairinterface5g
  • dzxu/openairinterface5g
  • ptizoom/openairinterface5g
  • Thierry/openairinterface5g
  • tjamc80/openairinterface5g
  • yenmuse/openairinterface5g
  • archerling/openairinterface5g
  • grahul/openairinterface5g
  • ashish.shri/openairinterface5g
  • TianyuChen/openairinterface5g
  • cuixf1/openairinterface5g
  • Jan/openairinterface5g
  • jboatenng/openairinterface5g_gpio
  • geokal/openairinterface5g
  • johannhg/openairinterface5g
  • TofunmiA/openairinterface5g
  • razvanursu/openairinterface5g-mac-scheduling
  • Julio/openairinterface5g
  • fredrichx/openairinterface5g
  • nems/openairinterface5g
  • wb_li/openairinterface5g
  • ferrieux/openairinterface5g
  • prajna_g/openairinterface-5-g-xnap-ho
  • mtinasc/openairinterface5g
  • Hofschroeer/openairinterface5g
  • buptxiaofeng/openairinterface5g
  • fjgh_759/openairinterface5g
  • calcel/openairinterface5g
  • Reem/openairinterface5g
  • havar_mind/openairinterface5g
  • shrinish/openairinterface5g
  • YANGHELINDE/openairinterface5g
  • lool/openairinterface5g
  • raghav1900/openairinterface5g
  • allan1201/openairinterface5g
  • ferris/openairinterface5g
  • seanzw/openairinterface5g
  • emad72/openairinterface5g
  • guojilong123/openairinterface5g
  • Rony99/openairinterface5g
  • lity/openairinterface5g
  • sshrivastava/openairinterface5g
  • zhihengzhang/openairinterface5g
  • Rakesh_B_B/openairinterface5g
  • baleeiro/openairinterface5g
  • 19125064/openairinterface5g
  • linlin/openairinterface5g
  • NA1VE/openairinterface5g
  • oai1B/openairinterface5g
  • daveprice/openairinterface5g
  • mo/openairinterface5g
  • dhanmeet/openairinterface5g
  • mv2290/openairinterface-5-g-test
  • pagmatt/openairinterface5g
  • mmTestNYU/openairinterface5g
  • mmezzavilla/openairinterface5g
  • sudhakarb/openairinterface5g
  • mekki/openairinterface5g
  • virtanen/openairinterface5g
  • dyyu/openairinterface5g
  • mohammed_safwan/openairinterface5g
  • venkat/openairinterface5g
  • rupadhya/openairinterface5g
  • adjou/openairinterface5g
  • samiemostafavi/openairinterface5g-edaf
  • oliverxsch/openairinterface5g
  • Simewu/openairinterface5g
  • Sreeram/openairinterface5g
  • oai/openairinterface5g
161 results
Show changes
...@@ -1278,6 +1278,8 @@ void init_eNB_proc(int inst) { ...@@ -1278,6 +1278,8 @@ void init_eNB_proc(int inst) {
eNB_rxtx_proc_t *proc_rxtx; eNB_rxtx_proc_t *proc_rxtx;
pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL,*attr_td=NULL,*attr_te; pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL,*attr_td=NULL,*attr_te;
printf("%s()\n", __FUNCTION__);
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];
LOG_I(PHY,"Initializing eNB %d CC_id %d (%s,%s),\n",inst,CC_id,eNB_functions[eNB->node_function],eNB_timing[eNB->node_timing]); LOG_I(PHY,"Initializing eNB %d CC_id %d (%s,%s),\n",inst,CC_id,eNB_functions[eNB->node_function],eNB_timing[eNB->node_timing]);
...@@ -1673,10 +1675,15 @@ void init_RAN(RAN_CONTEXT *rc,eNB_func_t node_function[], eNB_timing_t node_timi ...@@ -1673,10 +1675,15 @@ void init_RAN(RAN_CONTEXT *rc,eNB_func_t node_function[], eNB_timing_t node_timi
PHY_VARS_eNB *eNB; PHY_VARS_eNB *eNB;
int ret; int ret;
printf("%s() rc->nb_inst:%d\n", __FUNCTION__, rc->nb_inst);
for (inst=0;inst<rc->nb_inst;inst++) { for (inst=0;inst<rc->nb_inst;inst++) {
printf("%s() rc->nb_inst:%d rc->nb_CC:%d\n", __FUNCTION__, rc->nb_inst, rc->nb_CC);
for (CC_id=0;CC_id<rc->nb_CC;CC_id++) { for (CC_id=0;CC_id<rc->nb_CC;CC_id++) {
eNB = rc->eNB[inst][CC_id]; eNB = rc->eNB[inst][CC_id];
printf("%s() rc->nb_inst:%d rc->nb_CC:%d eNB:%p rc->eNB[%d][%d]:%p\n", __FUNCTION__, rc->nb_inst, rc->nb_CC, eNB, inst, CC_id, rc->eNB[inst][CC_id]);
if (eNB) { if (eNB) {
eNB->node_function = node_function[CC_id]; eNB->node_function = node_function[CC_id];
eNB->node_timing = node_timing[CC_id]; eNB->node_timing = node_timing[CC_id];
eNB->abstraction_flag = 0; eNB->abstraction_flag = 0;
......
...@@ -129,6 +129,8 @@ int attach_rru(RU_t *ru); ...@@ -129,6 +129,8 @@ int attach_rru(RU_t *ru);
int connect_rau(RU_t *ru); int connect_rau(RU_t *ru);
extern uint8_t nfapi_mode;
extern uint16_t sf_ahead;
/*************************************************************/ /*************************************************************/
/* Functions to attach and configure RRU */ /* Functions to attach and configure RRU */
...@@ -388,8 +390,8 @@ void fh_if4p5_south_in(RU_t *ru,int *frame,int *subframe) { ...@@ -388,8 +390,8 @@ void fh_if4p5_south_in(RU_t *ru,int *frame,int *subframe) {
proc->frame_rx = f; proc->frame_rx = f;
proc->timestamp_rx = ((proc->frame_rx * 10) + proc->subframe_rx ) * fp->samples_per_tti ; proc->timestamp_rx = ((proc->frame_rx * 10) + proc->subframe_rx ) * fp->samples_per_tti ;
// proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti); // proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti);
proc->subframe_tx = (sf+4)%10; proc->subframe_tx = (sf+sf_ahead)%10;
proc->frame_tx = (sf>5) ? (f+1)&1023 : f; proc->frame_tx = (sf>(9-sf_ahead)) ? (f+1)&1023 : f;
if (proc->first_rx == 0) { if (proc->first_rx == 0) {
if (proc->subframe_rx != *subframe){ if (proc->subframe_rx != *subframe){
...@@ -591,6 +593,7 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *subframe) { ...@@ -591,6 +593,7 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *subframe) {
uint32_t symbol_number,symbol_mask,symbol_mask_full; uint32_t symbol_number,symbol_mask,symbol_mask_full;
int subframe_tx,frame_tx; int subframe_tx,frame_tx;
LOG_E(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru);
symbol_number = 0; symbol_number = 0;
symbol_mask = 0; symbol_mask = 0;
symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1; symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1;
...@@ -666,6 +669,7 @@ void fh_if4p5_north_out(RU_t *ru) { ...@@ -666,6 +669,7 @@ void fh_if4p5_north_out(RU_t *ru) {
stop_meas(&ru->tx_fhaul); stop_meas(&ru->tx_fhaul);
} }
void rx_rf(RU_t *ru,int *frame,int *subframe) { void rx_rf(RU_t *ru,int *frame,int *subframe) {
RU_proc_t *proc = &ru->proc; RU_proc_t *proc = &ru->proc;
...@@ -677,7 +681,7 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { ...@@ -677,7 +681,7 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
for (i=0; i<ru->nb_rx; i++) for (i=0; i<ru->nb_rx; i++)
rxp[i] = (void*)&ru->common.rxdata[i][*subframe*fp->samples_per_tti]; rxp[i] = (void*)&ru->common.rxdata[i][*subframe*fp->samples_per_tti];
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
old_ts = proc->timestamp_rx; old_ts = proc->timestamp_rx;
...@@ -692,8 +696,9 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { ...@@ -692,8 +696,9 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
proc->timestamp_rx = ts-ru->ts_offset; proc->timestamp_rx = ts-ru->ts_offset;
AssertFatal(rxs == fp->samples_per_tti, //AssertFatal(rxs == fp->samples_per_tti,
"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_tti,rxs); //"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_tti,rxs);
if (rxs != fp->samples_per_tti) LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_tti,rxs);
if (proc->first_rx == 1) { if (proc->first_rx == 1) {
ru->ts_offset = proc->timestamp_rx; ru->ts_offset = proc->timestamp_rx;
...@@ -711,15 +716,17 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { ...@@ -711,15 +716,17 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
// synchronize first reception to frame 0 subframe 0 // synchronize first reception to frame 0 subframe 0
proc->timestamp_tx = proc->timestamp_rx+(4*fp->samples_per_tti); proc->timestamp_tx = proc->timestamp_rx+(sf_ahead*fp->samples_per_tti);
proc->subframe_tx = (proc->subframe_rx+4)%10; proc->subframe_tx = (proc->subframe_rx+sf_ahead)%10;
proc->frame_tx = (proc->subframe_rx>5) ? (proc->frame_rx+1)&1023 : proc->frame_rx; proc->frame_tx = (proc->subframe_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
#if 0
LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, subframe %d\n", LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, subframe %d\n",
ru->idx, ru->idx,
0, 0,
(unsigned long long int)proc->timestamp_rx, (unsigned long long int)proc->timestamp_rx,
(int)ru->ts_offset,proc->frame_rx,proc->subframe_rx); (int)ru->ts_offset,proc->frame_rx,proc->subframe_rx);
#endif
// dump VCD output for first RU in list // dump VCD output for first RU in list
if (ru == RC.ru[0]) { if (ru == RC.ru[0]) {
...@@ -750,10 +757,9 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { ...@@ -750,10 +757,9 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
if (rxs != fp->samples_per_tti) if (rxs != fp->samples_per_tti)
exit_fun( "problem receiving samples" ); {
//exit_fun( "problem receiving samples" );
}
} }
...@@ -776,7 +782,6 @@ void tx_rf(RU_t *ru) { ...@@ -776,7 +782,6 @@ void tx_rf(RU_t *ru) {
if ((SF_type == SF_DL) || if ((SF_type == SF_DL) ||
(SF_type == SF_S)) { (SF_type == SF_S)) {
int siglen=fp->samples_per_tti,flags=1; int siglen=fp->samples_per_tti,flags=1;
if (SF_type == SF_S) { if (SF_type == SF_S) {
...@@ -814,8 +819,8 @@ void tx_rf(RU_t *ru) { ...@@ -814,8 +819,8 @@ void tx_rf(RU_t *ru) {
ru->nb_tx, ru->nb_tx,
flags); flags);
LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx, //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->subframe_tx); //(long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->subframe_tx);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
...@@ -940,22 +945,26 @@ static void* ru_thread_prach( void* param ) { ...@@ -940,22 +945,26 @@ static void* ru_thread_prach( void* param ) {
thread_top_init("ru_thread_prach",1,500000L,1000000L,20000000L); thread_top_init("ru_thread_prach",1,500000L,1000000L,20000000L);
LOG_E(PHY,"In rach thread\n");
while (RC.ru_mask>0) {
usleep(1e6);
LOG_I(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__);
}
LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__);
while (!oai_exit) { while (!oai_exit) {
if (oai_exit) break; if (oai_exit) break;
if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 );
rx_prach(NULL, prach_procedures(
ru, ru->eNB_list[0]
NULL,
NULL,
NULL,
proc->frame_prach,
0
#ifdef Rel14 #ifdef Rel14
,0 ,0
#endif #endif
); );
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );
if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
} }
...@@ -1105,21 +1114,29 @@ void wakeup_eNBs(RU_t *ru) { ...@@ -1105,21 +1114,29 @@ void wakeup_eNBs(RU_t *ru) {
int i; int i;
PHY_VARS_eNB **eNB_list = ru->eNB_list; PHY_VARS_eNB **eNB_list = ru->eNB_list;
LOG_D(PHY,"wakeup_eNBs (num %d) for RU %d\n",ru->num_eNB,ru->idx); //LOG_D(PHY,"wakeup_eNBs (num %d) for RU %d ru->eNB_top:%p\n",ru->num_eNB,ru->idx, ru->eNB_top);
if (ru->num_eNB==1) { if (ru->num_eNB==1 && ru->eNB_top!=0) {
// call eNB function directly // call eNB function directly
char string[20]; char string[20];
sprintf(string,"Incoming RU %d",ru->idx); sprintf(string,"Incoming RU %d",ru->idx);
LOG_D(PHY,"RU %d Waking up eNB\n",ru->idx); //LOG_D(PHY,"RU %d Call eNB_top\n",ru->idx);
ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string); ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string);
} }
else { else {
LOG_D(PHY,"ru->num_eNB:%d\n", ru->num_eNB);
for (i=0;i<ru->num_eNB;i++) for (i=0;i<ru->num_eNB;i++)
if (ru->wakeup_rxtx(eNB_list[i],ru) < 0) {
LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->wakeup_rxtx);
if (ru->wakeup_rxtx!=0 && ru->wakeup_rxtx(eNB_list[i],ru) < 0)
{
LOG_E(PHY,"could not wakeup eNB rxtx process for subframe %d\n", ru->proc.subframe_rx); LOG_E(PHY,"could not wakeup eNB rxtx process for subframe %d\n", ru->proc.subframe_rx);
}
}
} }
} }
...@@ -1140,7 +1157,11 @@ static inline int wakeup_prach_ru(RU_t *ru) { ...@@ -1140,7 +1157,11 @@ static inline int wakeup_prach_ru(RU_t *ru) {
ru->proc.frame_prach = ru->proc.frame_rx; ru->proc.frame_prach = ru->proc.frame_rx;
ru->proc.subframe_prach = ru->proc.subframe_rx; ru->proc.subframe_prach = ru->proc.subframe_rx;
LOG_D(PHY,"RU %d: waking up PRACH thread\n",ru->idx); // DJP - think prach_procedures() is looking at eNB frame_prach
ru->eNB_list[0]->proc.frame_prach = ru->proc.frame_rx;
ru->eNB_list[0]->proc.subframe_prach = ru->proc.subframe_rx;
//LOG_D(PHY,"RU %d: waking up PRACH thread\n",ru->idx);
// the thread can now be woken up // the thread can now be woken up
AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n"); AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n");
} }
...@@ -1179,6 +1200,40 @@ static inline int wakeup_prach_ru_br(RU_t *ru) { ...@@ -1179,6 +1200,40 @@ static inline int wakeup_prach_ru_br(RU_t *ru) {
} }
#endif #endif
#if 0
static inline int wakeup_nfapi_subframe_thread(RU_t *ru) {
int i;
PHY_VARS_eNB **eNB_list = ru->eNB_list;
LOG_D(PHY,"wakeup_nfapi_subframe_thread (num %d) for RU %d ru->eNB_top:%p\n",ru->num_eNB,ru->idx, ru->eNB_top);
if (ru->num_eNB==1 && ru->eNB_top!=0) {
// call eNB function directly
char string[20];
sprintf(string,"Incoming RU %d",ru->idx);
//LOG_D(PHY,"RU %d Call eNB_top\n",ru->idx);
ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string);
}
else {
LOG_D(PHY,"ru->num_eNB:%d\n", ru->num_eNB);
for (i=0;i<ru->num_eNB;i++)
{
LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->wakeup_rxtx);
if (ru->wakeup_rxtx!=0 && ru->wakeup_rxtx(eNB_list[i],ru) < 0)
{
LOG_E(PHY,"could not wakeup eNB rxtx process for subframe %d\n", ru->proc.subframe_rx);
}
}
}
}
#endif
// this is for RU with local RF unit // this is for RU with local RF unit
void fill_rf_config(RU_t *ru, char *rf_config_file) { void fill_rf_config(RU_t *ru, char *rf_config_file) {
...@@ -1363,7 +1418,6 @@ static void* ru_thread( void* param ) { ...@@ -1363,7 +1418,6 @@ static void* ru_thread( void* param ) {
init_frame_parms(&ru->frame_parms,1); init_frame_parms(&ru->frame_parms,1);
phy_init_RU(ru); phy_init_RU(ru);
ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
} }
if (setup_RU_buffers(ru)!=0) { if (setup_RU_buffers(ru)!=0) {
...@@ -1419,23 +1473,36 @@ static void* ru_thread( void* param ) { ...@@ -1419,23 +1473,36 @@ static void* ru_thread( void* param ) {
subframe++; subframe++;
} }
LOG_D(PHY,"RU thread (proc %p), frame %d (%p), subframe %d (%p)\n",
proc, frame,&frame,subframe,&subframe);
// synchronization on input FH interface, acquire signals/data and block // synchronization on input FH interface, acquire signals/data and block
if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&subframe); if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&subframe);
else AssertFatal(1==0, "No fronthaul interface at south port"); else AssertFatal(1==0, "No fronthaul interface at south port");
LOG_D(PHY,"AFTER fh_south_in - SFN/SF:%d%d RU->proc[RX:%d%d TX:%d%d] RC.eNB[0][0]:[RX:%d%d TX(SFN):%d]\n",
frame,subframe,
proc->frame_rx,proc->subframe_rx,
proc->frame_tx,proc->subframe_tx,
RC.eNB[0][0]->proc.frame_rx,RC.eNB[0][0]->proc.subframe_rx,
RC.eNB[0][0]->proc.frame_tx);
if (nfapi_mode == 1) // PNF
{
// This is the earliest I think we can do this
//wakeup_nfapi_subframe_thread();
}
LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n", if (0 && is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx))
ru->do_prach, LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n",
is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx), ru->do_prach,
proc->frame_rx,proc->subframe_rx); is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx),
proc->frame_rx,proc->subframe_rx);
if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)==1)) wakeup_prach_ru(ru); if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)==1)) {
wakeup_prach_ru(ru);
}
#ifdef Rel14 #ifdef Rel14
else if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>1)) wakeup_prach_ru_br(ru); else if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>1)) {
wakeup_prach_ru_br(ru);
}
#endif #endif
// adjust for timing offset between RU // adjust for timing offset between RU
...@@ -1449,12 +1516,15 @@ static void* ru_thread( void* param ) { ...@@ -1449,12 +1516,15 @@ static void* ru_thread( void* param ) {
// If this proc is to provide synchronization, do so // If this proc is to provide synchronization, do so
wakeup_slaves(proc); wakeup_slaves(proc);
//LOG_E(PHY,"RU %d/%d frame_tx %d, subframe_tx %d - wakeup_eNBs...\n",0,ru->idx,proc->frame_tx,proc->subframe_tx);
// wakeup all eNB processes waiting for this RU // wakeup all eNB processes waiting for this RU
if (ru->num_eNB>0) wakeup_eNBs(ru); if (ru->num_eNB>0) wakeup_eNBs(ru);
// wait until eNBs are finished subframe RX n and TX n+4 //LOG_E(PHY,"%s() Before wait_on_condition()\n", __FUNCTION__);
// wait until eNBs are finished subframe RX n and TX n+sf_ahead
wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread"); wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread");
//LOG_E(PHY,"%s() AFTER wait_on_condition() ru->feptx_prec:%p ru->fh_north_asynch_in:%p ru->feptx_ofdm:%p ru->fh_south_out:%p ru->fh_north_out:%p\n", __FUNCTION__, ru->feptx_prec, ru->fh_north_asynch_in, ru->feptx_ofdm, ru->fh_south_out, ru->fh_north_out);
// do TX front-end processing if needed (precoding and/or IDFTs) // 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);
...@@ -1465,7 +1535,6 @@ static void* ru_thread( void* param ) { ...@@ -1465,7 +1535,6 @@ static void* ru_thread( void* param ) {
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);
if (ru->fh_north_out) ru->fh_north_out(ru); if (ru->fh_north_out) ru->fh_north_out(ru);
} }
...@@ -1585,6 +1654,7 @@ void init_RU_proc(RU_t *ru) { ...@@ -1585,6 +1654,7 @@ void init_RU_proc(RU_t *ru) {
#endif #endif
char name[100]; char name[100];
LOG_E(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,eNB_functions[ru->function],eNB_timing[ru->if_timing]);
#ifndef OCP_FRAMEWORK #ifndef OCP_FRAMEWORK
LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,eNB_functions[ru->function],eNB_timing[ru->if_timing]); LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,eNB_functions[ru->function],eNB_timing[ru->if_timing]);
#endif #endif
...@@ -1639,6 +1709,8 @@ void init_RU_proc(RU_t *ru) { ...@@ -1639,6 +1709,8 @@ void init_RU_proc(RU_t *ru) {
pthread_create( &proc->pthread_FH, attr_FH, ru_thread, (void*)ru ); pthread_create( &proc->pthread_FH, attr_FH, ru_thread, (void*)ru );
LOG_E(PHY,"%s() DJP - ru->function:%d\n", __FUNCTION__, ru->function);
if (ru->function == NGFI_RRU_IF4p5) { if (ru->function == NGFI_RRU_IF4p5) {
pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void*)ru ); pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void*)ru );
#ifdef Rel14 #ifdef Rel14
...@@ -1655,6 +1727,10 @@ void init_RU_proc(RU_t *ru) { ...@@ -1655,6 +1727,10 @@ void init_RU_proc(RU_t *ru) {
pthread_setname_np( proc->pthread_FH, name ); pthread_setname_np( proc->pthread_FH, name );
} }
else if (ru->function == eNodeB_3GPP && ru->if_south == LOCAL_RF) { // DJP - need something else to distinguish between monolithic and PNF
LOG_E(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__);
pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void*)ru );
}
if (get_nprocs()>=2) { if (get_nprocs()>=2) {
if (ru->feprx) init_fep_thread(ru,NULL); if (ru->feprx) init_fep_thread(ru,NULL);
...@@ -1664,10 +1740,6 @@ void init_RU_proc(RU_t *ru) { ...@@ -1664,10 +1740,6 @@ void init_RU_proc(RU_t *ru) {
} }
int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) { int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) {
FH_fmt_options_t fmt = cap->FH_fmt; FH_fmt_options_t fmt = cap->FH_fmt;
...@@ -1865,10 +1937,13 @@ void init_RU(char *rf_config_file) { ...@@ -1865,10 +1937,13 @@ void init_RU(char *rf_config_file) {
RCconfig_RU(); RCconfig_RU();
LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",RC.nb_L1_inst,RC.nb_RU,get_nprocs()); LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",RC.nb_L1_inst,RC.nb_RU,get_nprocs());
for (i=0;i<RC.nb_L1_inst;i++) if (RC.nb_CC != 0)
for (CC_id=0;CC_id<RC.nb_CC[i];CC_id++) RC.eNB[i][CC_id]->num_RU=0; for (i=0;i<RC.nb_L1_inst;i++)
for (CC_id=0;CC_id<RC.nb_CC[i];CC_id++) RC.eNB[i][CC_id]->num_RU=0;
LOG_E(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU);
for (ru_id=0;ru_id<RC.nb_RU;ru_id++) { for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
LOG_E(PHY,"Process RC.ru[%d]\n",ru_id);
ru = RC.ru[ru_id]; ru = RC.ru[ru_id];
ru->rf_config_file = rf_config_file; ru->rf_config_file = rf_config_file;
ru->idx = ru_id; ru->idx = ru_id;
...@@ -1876,24 +1951,47 @@ void init_RU(char *rf_config_file) { ...@@ -1876,24 +1951,47 @@ void init_RU(char *rf_config_file) {
// use eNB_list[0] as a reference for RU frame parameters // use eNB_list[0] as a reference for RU frame parameters
// NOTE: multiple CC_id are not handled here yet! // NOTE: multiple CC_id are not handled here yet!
printf("%s() RC.ru[%d].num_eNB:%d ru->eNB_list[0]:%p RC.eNB[0][0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file);
eNB0 = ru->eNB_list[0];
if ((ru->function != NGFI_RRU_IF5) && (ru->function != NGFI_RRU_IF4p5))
AssertFatal(eNB0!=NULL,"eNB0 is null!\n");
if (eNB0) { if (ru->eNB_list[0] == 0)
LOG_I(PHY,"Copying frame parms from eNB %d to ru %d\n",eNB0->Mod_id,ru->idx); {
memcpy((void*)&ru->frame_parms,(void*)&eNB0->frame_parms,sizeof(LTE_DL_FRAME_PARMS)); LOG_E(PHY,"%s() DJP - ru->eNB_list ru->num_eNB are not initialized - so do it manually\n", __FUNCTION__);
ru->eNB_list[0] = RC.eNB[0][0];
ru->num_eNB=1;
//
// DJP - feptx_prec() / feptx_ofdm() parses the eNB_list (based on num_eNB) and copies the txdata_F to txdata in RU
//
}
else
{
LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__);
}
// attach all RU to all eNBs in its list/ eNB0 = ru->eNB_list[0];
for (i=0;i<ru->num_eNB;i++) { printf("RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south);
eNB0 = ru->eNB_list[i]; printf("eNB0:%p\n", eNB0);
eNB0->RU_list[eNB0->num_RU++] = ru; if (eNB0)
{
if ((ru->function != NGFI_RRU_IF5) && (ru->function != NGFI_RRU_IF4p5))
AssertFatal(eNB0!=NULL,"eNB0 is null!\n");
if (eNB0) {
LOG_I(PHY,"Copying frame parms from eNB %d to ru %d\n",eNB0->Mod_id,ru->idx);
memcpy((void*)&ru->frame_parms,(void*)&eNB0->frame_parms,sizeof(LTE_DL_FRAME_PARMS));
// attach all RU to all eNBs in its list/
LOG_E(PHY,"ru->num_eNB:%d eNB0->num_RU:%d\n", ru->num_eNB, eNB0->num_RU);
for (i=0;i<ru->num_eNB;i++) {
eNB0 = ru->eNB_list[i];
eNB0->RU_list[eNB0->num_RU++] = ru;
}
} }
} }
// LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],eNB_timing[ru->if_timing],ru->function); // LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],eNB_timing[ru->if_timing],ru->function);
LOG_E(PHY,"ru->if_south:%d\n", ru->if_south);
switch (ru->if_south) { switch (ru->if_south) {
case LOCAL_RF: // this is an RU with integrated RF (RRU, eNB) case LOCAL_RF: // this is an RU with integrated RF (RRU, eNB)
if (ru->function == NGFI_RRU_IF5) { // IF5 RRU if (ru->function == NGFI_RRU_IF5) { // IF5 RRU
...@@ -1968,7 +2066,8 @@ void init_RU(char *rf_config_file) { ...@@ -1968,7 +2066,8 @@ void init_RU(char *rf_config_file) {
if (setup_RU_buffers(ru)!=0) { if (setup_RU_buffers(ru)!=0) {
printf("Exiting, cannot initialize RU Buffers\n"); printf("Exiting, cannot initialize RU Buffers\n");
exit(-1); exit(-1);
}*/ }
*/
break; break;
case REMOTE_IF5: // the remote unit is IF5 RRU case REMOTE_IF5: // the remote unit is IF5 RRU
......
/*
* lte-softmodem-stub.c
*
* Created on: Nov 27, 2017
* Author: montre
*/
/*
* 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 lte-enb.c
* \brief Top-level threads for eNodeB
* \author R. Knopp, F. Kaltenberger, Navid Nikaein
* \date 2012
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
* \note
* \warning
*/
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <sched.h>
#include "T.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.h"
#include "common/ran_context.h"
#include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.h"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //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/if_defs.h"
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
#include "PHY/vars.h"
#include "SCHED/vars.h"
#include "LAYER2/MAC/vars.h"
#include "../../SIMU/USER/init_lte.h"
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/vars.h"
#include "LAYER2/MAC/proto.h"
#include "RRC/LITE/vars.h"
#include "PHY_INTERFACE/vars.h"
#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif
#include "UTIL/LOG/log_extern.h"
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "enb_config.h"
//#include "PHY/TOOLS/time_meas.h"
#ifndef OPENAIR2
#include "UTIL/OTG/otg_vars.h"
#endif
#if defined(ENABLE_ITTI)
#include "intertask_interface_init.h"
#include "create_tasks.h"
#endif
#include "system.h"
#ifdef XFORMS
#include "PHY/TOOLS/lte_phy_scope.h"
#include "stats.h"
#endif
#include "lte-softmodem.h"
#ifdef XFORMS
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
// at eNB 0, an UL scope for every UE
FD_lte_phy_scope_ue *form_ue[NUMBER_OF_UE_MAX];
FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
FD_stats_form *form_stats=NULL,*form_stats_l2=NULL;
char title[255];
unsigned char scope_enb_num_ue = 2;
static pthread_t forms_thread; //xforms
#endif //XFORMS
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
uint8_t nfapi_mode = 3;
uint16_t sf_ahead=4;
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
int config_sync_var=-1;
uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
#if defined(ENABLE_ITTI)
volatile int start_eNB = 0;
volatile int start_UE = 0;
#endif
volatile int oai_exit = 0;
static clock_source_t clock_source = internal;
static int wait_for_sync = 0;
static char UE_flag=0;
unsigned int mmapped_dma=0;
int single_thread_flag=1;
static char threequarter_fs=0;
uint32_t downlink_frequency[MAX_NUM_CCs][4];
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
#if defined(ENABLE_ITTI)
static char *itti_dump_file = NULL;
#endif
int UE_scan = 1;
int UE_scan_carrier = 0;
runmode_t mode = normal_txrx;
FILE *input_fd=NULL;
#if MAX_NUM_CCs == 1
rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
#else
rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}};
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
#endif
double rx_gain_off = 0.0;
double sample_rate=30.72e6;
double bw = 10.0e6;
static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/;
char rf_config_file[1024];
int chain_offset=0;
int phy_test = 0;
uint8_t usim_test = 0;
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
char ref[128] = "internal";
char channels[128] = "0";
int rx_input_level_dBm;
#ifdef XFORMS
extern int otg_enabled;
static char do_forms=0;
#else
int otg_enabled;
#endif
//int number_of_cards = 1;
static LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
uint32_t target_dl_mcs = 28; //maximum allowed mcs
uint32_t target_ul_mcs = 20;
uint32_t timing_advance = 0;
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
extern PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t UE_id,
uint8_t abstraction_flag);
extern void init_eNB_afterRU(void);
extern void init_UE_stub(int nb_inst,int,int);
extern int init_timer_thread(void);
int transmission_mode=1;
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;
openair0_config_t openair0_cfg[MAX_CARDS];
double cpuf;
extern char uecap_xer[1024];
char uecap_xer_in=0;
int oaisim_flag=0;
threads_t threads= {-1,-1,-1,-1,-1,-1,-1};
/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
* this is very hackish - find a proper solution
*/
uint8_t abstraction_flag=0;
/*---------------------BMC: timespec helpers -----------------------------*/
struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
struct timespec clock_difftime(struct timespec start, struct timespec end) {
struct timespec temp;
if ((end.tv_nsec-start.tv_nsec)<0) {
temp.tv_sec = end.tv_sec-start.tv_sec-1;
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
} else {
temp.tv_sec = end.tv_sec-start.tv_sec;
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
}
return temp;
}
void print_difftimes(void) {
#ifdef DEBUG
printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#else
LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#endif
}
void update_difftimes(struct timespec start, struct timespec end) {
struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
int changed = 0;
diff_time = clock_difftime(start, end);
if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) {
min_diff_time.tv_nsec = diff_time.tv_nsec;
changed = 1;
}
if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) {
max_diff_time.tv_nsec = diff_time.tv_nsec;
changed = 1;
}
#if 1
if (changed) print_difftimes();
#endif
}
/*------------------------------------------------------------------------*/
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
}
#if !defined(ENABLE_ITTI)
void signal_handler(int sig) {
void *array[10];
size_t size;
if (sig==SIGSEGV) {
// get void*'s for all entries on the stack
size = backtrace(array, 10);
// print out all the frames to stderr
fprintf(stderr, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, 2);
exit(-1);
} else {
printf("trying to exit gracefully...\n");
oai_exit = 1;
}
}
#endif
#define KNRM "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
#define KBLU "\x1B[34m"
#define RESET "\033[0m"
void exit_fun(const char* s)
{
int CC_id;
int ru_id;
if (s != NULL) {
printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
}
oai_exit = 1;
if (UE_flag==0) {
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);
if (RC.ru[ru_id]->ifdevice.trx_end_func)
RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
}
}
for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
oai_exit = 1;
for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
if (UE_flag == 0) {
} else {
if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func)
PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice);
}
}
#if defined(ENABLE_ITTI)
sleep(1); //allow lte-softmodem threads to exit first
itti_terminate_tasks (TASK_UNKNOWN);
#endif
}
}
#ifdef XFORMS
void reset_stats(FL_OBJECT *button, long arg)
{
int i,j,k;
PHY_VARS_eNB *phy_vars_eNB = RC.eNB[0][0];
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
for (k=0; k<8; k++) { //harq_processes
for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0;
phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0;
phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0;
}
phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0;
phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0;
phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0;
phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0;
phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0;
phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0;
}
}
}
static void *scope_thread(void *arg) {
char stats_buffer[16384];
# ifdef ENABLE_XFORMS_WRITE_STATS
FILE *UE_stats, *eNB_stats;
# endif
struct sched_param sched_param;
int UE_id, CC_id;
int ue_cnt=0;
sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
sched_setscheduler(0, SCHED_FIFO,&sched_param);
printf("Scope thread has priority %d\n",sched_param.sched_priority);
# ifdef ENABLE_XFORMS_WRITE_STATS
if (UE_flag==1)
UE_stats = fopen("UE_stats.txt", "w");
else
eNB_stats = fopen("eNB_stats.txt", "w");
#endif
while (!oai_exit) {
if (UE_flag==1) {
dump_ue_stats (PHY_vars_UE_g[0][0], &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0],stats_buffer, 0, mode,rx_input_level_dBm);
//fl_set_object_label(form_stats->stats_text, stats_buffer);
fl_clear_browser(form_stats->stats_text);
fl_add_browser_line(form_stats->stats_text, stats_buffer);
phy_scope_UE(form_ue[0],
PHY_vars_UE_g[0][0],
0,
0,7);
} else {
/*
if (RC.eNB[0][0]->mac_enabled==1) {
len = dump_eNB_l2_stats (stats_buffer, 0);
//fl_set_object_label(form_stats_l2->stats_text, stats_buffer);
fl_clear_browser(form_stats_l2->stats_text);
fl_add_browser_line(form_stats_l2->stats_text, stats_buffer);
}
len = dump_eNB_stats (RC.eNB[0][0], stats_buffer, 0);
if (MAX_NUM_CCs>1)
len += dump_eNB_stats (RC.eNB[0][1], &stats_buffer[len], 0);
//fl_set_object_label(form_stats->stats_text, stats_buffer);
fl_clear_browser(form_stats->stats_text);
fl_add_browser_line(form_stats->stats_text, stats_buffer);
*/
ue_cnt=0;
for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
// if ((RC.eNB[0][CC_id]->dlsch[UE_id][0]->rnti>0) && (ue_cnt<scope_enb_num_ue)) {
if ((ue_cnt<scope_enb_num_ue)) {
phy_scope_eNB(form_enb[CC_id][ue_cnt],
RC.eNB[0][CC_id],
UE_id);
ue_cnt++;
}
}
}
}
//printf("doing forms\n");
//usleep(100000); // 100 ms
sleep(1);
}
// printf("%s",stats_buffer);
# ifdef ENABLE_XFORMS_WRITE_STATS
if (UE_flag==1) {
if (UE_stats) {
rewind (UE_stats);
fwrite (stats_buffer, 1, len, UE_stats);
fclose (UE_stats);
}
} else {
if (eNB_stats) {
rewind (eNB_stats);
fwrite (stats_buffer, 1, len, eNB_stats);
fclose (eNB_stats);
}
}
# endif
pthread_exit((void*)arg);
}
#endif
#if defined(ENABLE_ITTI)
void *l2l1_task(void *arg) {
MessageDef *message_p = NULL;
int result;
itti_set_task_real_time(TASK_L2L1);
itti_mark_task_ready(TASK_L2L1);
if (UE_flag == 0) {
/* Wait for the initialize message */
printf("Wait for the ITTI initialize message\n");
do {
if (message_p != NULL) {
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}
itti_receive_msg (TASK_L2L1, &message_p);
switch (ITTI_MSG_ID(message_p)) {
case INITIALIZE_MESSAGE:
/* Start eNB thread */
LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
start_eNB = 1;
break;
case TERMINATE_MESSAGE:
printf("received terminate message\n");
oai_exit=1;
itti_exit_task ();
break;
default:
LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
break;
}
} while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}
do {
// Wait for a message
itti_receive_msg (TASK_L2L1, &message_p);
switch (ITTI_MSG_ID(message_p)) {
case TERMINATE_MESSAGE:
oai_exit=1;
itti_exit_task ();
break;
case ACTIVATE_MESSAGE:
start_UE = 1;
break;
case DEACTIVATE_MESSAGE:
start_UE = 0;
break;
case MESSAGE_TEST:
LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
break;
default:
LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
break;
}
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
} while(!oai_exit);
return NULL;
}
#endif
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
int CC_id;
printf("Panos: set_default_frame_parms1 %d \n",MAX_NUM_CCs);
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
frame_parms[CC_id] = (LTE_DL_FRAME_PARMS*) malloc(sizeof(LTE_DL_FRAME_PARMS));
/* Set some default values that may be overwritten while reading options */
frame_parms[CC_id]->frame_type = FDD;
frame_parms[CC_id]->tdd_config = 3;
frame_parms[CC_id]->tdd_config_S = 0;
frame_parms[CC_id]->N_RB_DL = 100;
frame_parms[CC_id]->N_RB_UL = 100;
frame_parms[CC_id]->Ncp = NORMAL;
frame_parms[CC_id]->Ncp_UL = NORMAL;
frame_parms[CC_id]->Nid_cell = 0;
frame_parms[CC_id]->num_MBSFN_config = 0;
frame_parms[CC_id]->nb_antenna_ports_eNB = 1;
frame_parms[CC_id]->nb_antennas_tx = 1;
frame_parms[CC_id]->nb_antennas_rx = 1;
frame_parms[CC_id]->nushift = 0;
frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth;
frame_parms[CC_id]->phich_config_common.phich_duration = normal;
// UL RS Config
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0;
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0;
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;
frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;
downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31.
downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
//printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
}
}
static void get_options(void) {
int CC_id;
int tddflag;
char *loopfile=NULL;
int dumpframe;
uint32_t online_log_messages;
uint32_t glog_level, glog_verbosity;
uint32_t start_telnetsrv;
printf("Panos: get_options 1 \n");
paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL);
printf("get_options 0, UE_flag: %d", UE_flag);
printf("Panos: get_options 2 \n");
if (strlen(in_path) > 0) {
opt_type = OPT_PCAP;
opt_enabled=1;
printf("Enabling OPT for PCAP with the following file %s \n",in_path);
}
if (strlen(in_ip) > 0) {
opt_enabled=1;
opt_type = OPT_WIRESHARK;
printf("Enabling OPT for wireshark for local interface");
}
printf("Panos: get_options 3 \n");
config_process_cmdline( cmdline_logparams,sizeof(cmdline_logparams)/sizeof(paramdef_t),NULL);
if(config_isparamset(cmdline_logparams,CMDLINE_ONLINELOG_IDX)) {
set_glog_onlinelog(online_log_messages);
}
if(config_isparamset(cmdline_logparams,CMDLINE_GLOGLEVEL_IDX)) {
set_glog(glog_level, -1);
}
if(config_isparamset(cmdline_logparams,CMDLINE_GLOGVERBO_IDX)) {
set_glog(-1, glog_verbosity);
}
if (start_telnetsrv) {
load_module_shlib("telnetsrv",NULL,0);
}
printf("Panos: get_options 4 \n");
if (UE_flag > 0) {
// set default parameters
set_default_frame_parms(frame_parms);
paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
printf("Panos: get_options 5 \n");
config_process_cmdline( cmdline_uemodeparams,sizeof(cmdline_uemodeparams)/sizeof(paramdef_t),NULL);
config_process_cmdline( cmdline_ueparams,sizeof(cmdline_ueparams)/sizeof(paramdef_t),NULL);
printf("Panos: get_options 6 \n");
if (loopfile != NULL) {
printf("Input file for hardware emulation: %s",loopfile);
mode=loop_through_memory;
input_fd = fopen(loopfile,"r");
AssertFatal(input_fd != NULL,"Please provide a valid input file\n");
}
printf("Panos: get_options 7 \n");
if ( (cmdline_uemodeparams[CMDLINE_CALIBUERX_IDX].paramflags & PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue;
printf("Panos: get_options 8 \n");
if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXMED_IDX].paramflags & PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_med;
printf("Panos: get_options 9 \n");
if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXBYP_IDX].paramflags & PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_byp;
printf("Panos: get_options 10 \n");
if ( cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr != NULL) {
if ( *(cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr) > 0) mode = debug_prach;
if ( *(cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr) > 0) mode = no_L2_connect;
if ( *(cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr) > 0) mode = calib_prach_tx;
}
printf("Panos: get_options 11 \n");
if (dumpframe > 0) mode = rx_dump_frame;
if ( downlink_frequency[0][0] > 0) {
printf("Panos: get_options 8 \n");
for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
downlink_frequency[CC_id][1] = downlink_frequency[0][0];
downlink_frequency[CC_id][2] = downlink_frequency[0][0];
downlink_frequency[CC_id][3] = downlink_frequency[0][0];
printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
}
UE_scan=0;
}
printf("Panos: get_options 15 \n");
if (tddflag > 0) {
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
frame_parms[CC_id]->frame_type = TDD;
}
printf("Panos: get_options 16 \n");
if (frame_parms != NULL){
printf("Panos: get_options 17 \n");
if (frame_parms[0]->N_RB_DL !=0) {
printf("Panos: get_options 17 \n");
if ( frame_parms[0]->N_RB_DL < 6 ) {
frame_parms[0]->N_RB_DL = 6;
printf ( "%i: Invalid number of ressource blocks, adjusted to 6\n",frame_parms[0]->N_RB_DL);
}
if ( frame_parms[0]->N_RB_DL > 100 ) {
frame_parms[0]->N_RB_DL = 100;
printf ( "%i: Invalid number of ressource blocks, adjusted to 100\n",frame_parms[0]->N_RB_DL);
}
if ( frame_parms[0]->N_RB_DL > 50 && frame_parms[0]->N_RB_DL < 100 ) {
frame_parms[0]->N_RB_DL = 50;
printf ( "%i: Invalid number of ressource blocks, adjusted to 50\n",frame_parms[0]->N_RB_DL);
}
if ( frame_parms[0]->N_RB_DL > 25 && frame_parms[0]->N_RB_DL < 50 ) {
frame_parms[0]->N_RB_DL = 25;
printf ( "%i: Invalid number of ressource blocks, adjusted to 25\n",frame_parms[0]->N_RB_DL);
}
UE_scan = 0;
frame_parms[0]->N_RB_UL=frame_parms[0]->N_RB_DL;
for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
frame_parms[CC_id]->N_RB_DL=frame_parms[0]->N_RB_DL;
frame_parms[CC_id]->N_RB_UL=frame_parms[0]->N_RB_UL;
}
}
}
printf("Panos: get_options 17 \n");
for (CC_id=1;CC_id<MAX_NUM_CCs;CC_id++) {
tx_max_power[CC_id]=tx_max_power[0];
rx_gain[0][CC_id] = rx_gain[0][0];
tx_gain[0][CC_id] = tx_gain[0][0];
}
printf("Panos: get_options 6 \n");
} /* UE_flag > 0 */
#if T_TRACER
paramdef_t cmdline_ttraceparams[] =CMDLINE_TTRACEPARAMS_DESC ;
config_process_cmdline( cmdline_ttraceparams,sizeof(cmdline_ttraceparams)/sizeof(paramdef_t),NULL);
#endif
if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
if (UE_flag == 0) {
memset((void*)&RC,0,sizeof(RC));
/* Read RC configuration file */
RCConfig();
NB_eNB_INST = RC.nb_inst;
NB_RU = RC.nb_RU;
printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,NB_RU);
}
} else if (UE_flag == 1 && (CONFIG_GETCONFFILE != NULL)) {
// Here the configuration file is the XER encoded UE capabilities
// Read it in and store in asn1c data structures
strcpy(uecap_xer,CONFIG_GETCONFFILE);
uecap_xer_in=1;
printf("Panos: get_options 7 \n");
} /* UE with config file */
}
#if T_TRACER
int T_nowait = 0; /* by default we wait for the tracer */
int T_port = 2021; /* default port to listen to to wait for the tracer */
int T_dont_fork = 0; /* default is to fork, see 'T_init' to understand */
#endif
void init_openair0(void);
void init_openair0() {
int card;
int i;
for (card=0; card<MAX_CARDS; card++) {
openair0_cfg[card].mmapped_dma=mmapped_dma;
openair0_cfg[card].configFilename = NULL;
if(frame_parms[0]->N_RB_DL == 100) {
if (frame_parms[0]->threequarter_fs) {
openair0_cfg[card].sample_rate=23.04e6;
openair0_cfg[card].samples_per_frame = 230400;
openair0_cfg[card].tx_bw = 10e6;
openair0_cfg[card].rx_bw = 10e6;
} else {
openair0_cfg[card].sample_rate=30.72e6;
openair0_cfg[card].samples_per_frame = 307200;
openair0_cfg[card].tx_bw = 10e6;
openair0_cfg[card].rx_bw = 10e6;
}
} else if(frame_parms[0]->N_RB_DL == 50) {
openair0_cfg[card].sample_rate=15.36e6;
openair0_cfg[card].samples_per_frame = 153600;
openair0_cfg[card].tx_bw = 5e6;
openair0_cfg[card].rx_bw = 5e6;
} else if (frame_parms[0]->N_RB_DL == 25) {
openair0_cfg[card].sample_rate=7.68e6;
openair0_cfg[card].samples_per_frame = 76800;
openair0_cfg[card].tx_bw = 2.5e6;
openair0_cfg[card].rx_bw = 2.5e6;
} else if (frame_parms[0]->N_RB_DL == 6) {
openair0_cfg[card].sample_rate=1.92e6;
openair0_cfg[card].samples_per_frame = 19200;
openair0_cfg[card].tx_bw = 1.5e6;
openair0_cfg[card].rx_bw = 1.5e6;
}
if (frame_parms[0]->frame_type==TDD)
openair0_cfg[card].duplex_mode = duplex_mode_TDD;
else //FDD
openair0_cfg[card].duplex_mode = duplex_mode_FDD;
printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx),
((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx));
openair0_cfg[card].Mod_id = 0;
openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
openair0_cfg[card].clock_source = clock_source;
openair0_cfg[card].tx_num_channels=min(2,((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx));
openair0_cfg[card].rx_num_channels=min(2,((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx));
for (i=0; i<4; i++) {
if (i<openair0_cfg[card].tx_num_channels)
openair0_cfg[card].tx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] : downlink_frequency[0][i]+uplink_frequency_offset[0][i];
else
openair0_cfg[card].tx_freq[i]=0.0;
if (i<openair0_cfg[card].rx_num_channels)
openair0_cfg[card].rx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] + uplink_frequency_offset[0][i] : downlink_frequency[0][i];
else
openair0_cfg[card].rx_freq[i]=0.0;
openair0_cfg[card].autocal[i] = 1;
openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
if (UE_flag == 0) {
openair0_cfg[card].rx_gain[i] = RC.eNB[0][0]->rx_total_gain_dB;
}
else {
openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB - rx_gain_off;
}
openair0_cfg[card].configFilename = rf_config_file;
printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
card,i, openair0_cfg[card].tx_gain[i],
openair0_cfg[card].rx_gain[i],
openair0_cfg[card].tx_freq[i],
openair0_cfg[card].rx_freq[i]);
}
}
}
void wait_RUs(void) {
LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
// 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);
printf("RC.ru_mask:%02lx\n", RC.ru_mask);
}
LOG_I(PHY,"RUs configured\n");
}
void wait_eNBs(void) {
int i,j;
int waiting=1;
while (waiting==1) {
printf("Waiting for eNB L1 instances to all get configured ... sleeping 500ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
usleep(5000000);
waiting=0;
for (i=0;i<RC.nb_L1_inst;i++) {
printf("RC.nb_L1_CC[%d]:%d\n", i, RC.nb_L1_CC[i]);
for (j=0;j<RC.nb_L1_CC[i];j++) {
if (RC.eNB[i][j]->configured==0) {
waiting=1;
break;
}
}
}
}
printf("eNB L1 are configured\n");
}
static inline void wait_nfapi_init(char *thread_name) {
printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
pthread_mutex_lock( &nfapi_sync_mutex );
while (nfapi_sync_var<0)
pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
pthread_mutex_unlock(&nfapi_sync_mutex);
printf( "NFAPI: got sync (%s)\n", thread_name);
}
int main( int argc, char **argv )
{
int i;
#if defined (XFORMS)
void *status;
#endif
int CC_id;
int ru_id;
uint8_t abstraction_flag=0;
uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
#if defined (XFORMS)
int ret;
#endif
start_background_system();
if ( load_configmodule(argc,argv) == NULL) {
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
}
#ifdef DEBUG_CONSOLE
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
#endif
PHY_VARS_UE *UE[MAX_NUM_CCs];
mode = normal_txrx;
//Panos: RF-sepcific part should get dropped (next 3 lines)?
//memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
//memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
//set_latency_target();
// set default parameters
//if (UE_flag == 1) set_default_frame_parms(frame_parms);
logInit();
printf("Reading in command-line options\n");
get_options ();
if (CONFIG_ISFLAGSET(CONFIG_ABORT)) {
fprintf(stderr,"Getting configuration failed\n");
exit(-1);
}
#if T_TRACER
T_init(T_port, 1-T_nowait, T_dont_fork);
#endif
//randominit (0);
set_taus_seed (0);
if (UE_flag==1) {
printf("configuring for UE\n");
set_comp_log(HW, LOG_DEBUG, LOG_HIGH, 1);
set_comp_log(PHY, LOG_DEBUG, LOG_HIGH, 1);
set_comp_log(MAC, LOG_INFO, LOG_HIGH, 1);
set_comp_log(RLC, LOG_INFO, LOG_HIGH | FLAG_THREAD, 1);
set_comp_log(PDCP, LOG_INFO, LOG_HIGH, 1);
set_comp_log(OTG, LOG_INFO, LOG_HIGH, 1);
set_comp_log(RRC, LOG_INFO, LOG_HIGH, 1);
#if defined(ENABLE_ITTI)
set_comp_log(EMU, LOG_INFO, LOG_MED, 1);
# if defined(ENABLE_USE_MME)
set_comp_log(NAS, LOG_INFO, LOG_HIGH, 1);
# endif
#endif
} else {
printf("configuring for RAU/RRU\n");
}
if (ouput_vcd) {
if (UE_flag==1)
VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
else
VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
}
// Panos: Not required for phy_stub_UE mode
/*if (opp_enabled ==1) {
reset_opp_meas();
}
cpuf=get_cpu_freq_GHz();*/
#if defined(ENABLE_ITTI)
if (UE_flag == 1) {
log_set_instance_type (LOG_INSTANCE_UE);
} else {
log_set_instance_type (LOG_INSTANCE_ENB);
}
printf("ITTI init\n");
itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
// initialize mscgen log after ITTI
MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
#endif
if (opt_type != OPT_NONE) {
radio_type_t radio_type;
if (frame_parms[0]->frame_type == FDD)
radio_type = RADIO_TYPE_FDD;
else
radio_type = RADIO_TYPE_TDD;
if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
LOG_E(OPT,"failed to run OPT \n");
}
#ifdef PDCP_USE_NETLINK
printf("PDCP netlink\n");
netlink_init();
#if defined(PDCP_USE_NETLINK_QUEUES)
pdcp_netlink_init();
#endif
#endif
#if !defined(ENABLE_ITTI)
// to make a graceful exit when ctrl-c is pressed
signal(SIGSEGV, signal_handler);
signal(SIGINT, signal_handler);
#endif
check_clock();
#ifndef PACKAGE_VERSION
# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
// init the parameters
// Panos: Probably don't need next lines for the stub.
/*for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
if (UE_flag==1) {
frame_parms[CC_id]->nb_antennas_tx = nb_antenna_tx;
frame_parms[CC_id]->nb_antennas_rx = nb_antenna_rx;
frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later
}
}*/
printf("Before CC \n");
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
if (UE_flag==1) {
NB_UE_INST=1;
NB_INST=1;
PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
PHY_vars_UE_g[0][CC_id] = init_ue_vars(frame_parms[CC_id], 0,abstraction_flag);
UE[CC_id] = PHY_vars_UE_g[0][CC_id];
printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]);
if (phy_test==1)
UE[CC_id]->mac_enabled = 0;
else
UE[CC_id]->mac_enabled = 1;
/*if (UE[CC_id]->mac_enabled == 0) { //set default UL parameters for testing mode
for (i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) {
UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK;
UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index = beta_RI;
UE[CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI;
UE[CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0;
UE[CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3);
UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;
}
}
UE[CC_id]->UE_scan = UE_scan;
UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
UE[CC_id]->mode = mode;
printf("UE[%d]->mode = %d\n",CC_id,mode);
if (UE[CC_id]->mac_enabled == 1) {
UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1234;
UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1234;
}else {
UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1235;
UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1235;
}
UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off;
UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
if (frame_parms[CC_id]->frame_type==FDD) {
UE[CC_id]->N_TA_offset = 0;
}
else {
if (frame_parms[CC_id]->N_RB_DL == 100)
UE[CC_id]->N_TA_offset = 624;
else if (frame_parms[CC_id]->N_RB_DL == 50)
UE[CC_id]->N_TA_offset = 624/2;
else if (frame_parms[CC_id]->N_RB_DL == 25)
UE[CC_id]->N_TA_offset = 624/4;
}*/
}
}
// Panos: Probably don't need these lines for phy_stub
/*printf("Runtime table\n");
fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
cpuf=get_cpu_freq_GHz();*/
#ifndef DEADLINE_SCHEDULER
printf("NO deadline scheduler\n");
/* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */
cpu_set_t cpuset;
int s;
char cpu_affinity[1024];
CPU_ZERO(&cpuset);
#ifdef CPU_AFFINITY
if (get_nprocs() > 2) {
CPU_SET(0, &cpuset);
s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
if (s != 0) {
perror( "pthread_setaffinity_np");
exit_fun("Error setting processor affinity");
}
LOG_I(HW, "Setting the affinity of main function to CPU 0, for device library to use CPU 0 only!\n");
}
#endif
/* Check the actual affinity mask assigned to the thread */
s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
if (s != 0) {
perror( "pthread_getaffinity_np");
exit_fun("Error getting processor affinity ");
}
memset(cpu_affinity, 0 , sizeof(cpu_affinity));
for (int j = 0; j < CPU_SETSIZE; j++) {
if (CPU_ISSET(j, &cpuset)) {
char temp[1024];
sprintf(temp, " CPU_%d ", j);
strcat(cpu_affinity, temp);
}
}
LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
#endif
#if defined(ENABLE_ITTI)
printf("ITTI enabled\n");
printf("UE_flag:%d\n", UE_flag);
printf("RC.nb_inst:%d\n", RC.nb_inst);
/*if ((UE_flag == 1)||
(RC.nb_inst > 0)) {*/
if (UE_flag == 1) {
// don't create if node doesn't connect to RRC/S1/GTP
if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
printf("cannot create ITTI tasks\n");
exit(-1); // need a softer mode
}
UE_config_stub_pnf();
printf("ITTI tasks created\n");
}
else {
printf("No ITTI, Initializing L1\n");
RCconfig_L1();
}
#endif
/*if (phy_test==0) {
if (UE_flag==1) {
printf("Filling UE band info\n");
fill_ue_band_info();
dl_phy_sync_success (0, 0, 0, 1);
}
}*/
mlockall(MCL_CURRENT | MCL_FUTURE);
// Panos: Why we have these initializations twice if in nfapi_mode?
pthread_cond_init(&sync_cond,NULL);
pthread_mutex_init(&sync_mutex, NULL);
#ifdef XFORMS
int UE_id;
printf("XFORMS\n");
if (do_forms==1) {
fl_initialize (&argc, argv, NULL, 0, 0);
if (UE_flag==0) {
form_stats_l2 = create_form_stats_form();
fl_show_form (form_stats_l2->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "l2 stats");
form_stats = create_form_stats_form();
fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats");
for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
form_enb[CC_id][UE_id] = create_lte_phy_scope_enb();
sprintf (title, "LTE UL SCOPE eNB for CC_id %d, UE %d",CC_id,UE_id);
fl_show_form (form_enb[CC_id][UE_id]->lte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
if (otg_enabled) {
fl_set_button(form_enb[CC_id][UE_id]->button_0,1);
fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic ON");
} else {
fl_set_button(form_enb[CC_id][UE_id]->button_0,0);
fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic OFF");
}
} // CC_id
} // UE_id
} else {
form_stats = create_form_stats_form();
fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats");
UE_id = 0;
form_ue[UE_id] = create_lte_phy_scope_ue();
sprintf (title, "LTE DL SCOPE UE");
fl_show_form (form_ue[UE_id]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
/*
if (openair_daq_vars.use_ia_receiver) {
fl_set_button(form_ue[UE_id]->button_0,1);
fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver ON");
} else {
fl_set_button(form_ue[UE_id]->button_0,0);
fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF");
}*/
fl_set_button(form_ue[UE_id]->button_0,0);
fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF");
}
ret = pthread_create(&forms_thread, NULL, scope_thread, NULL);
if (ret == 0)
pthread_setname_np( forms_thread, "xforms" );
printf("Scope thread created, ret=%d\n",ret);
}
#endif
rt_sleep_ns(10*100000000ULL);
if (nfapi_mode)
{
printf("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);
}
const char *nfapi_mode_str = "<UNKNOWN>";
switch(nfapi_mode)
{
case 0:
nfapi_mode_str = "MONOLITHIC";
break;
case 1:
nfapi_mode_str = "PNF";
break;
case 2:
nfapi_mode_str = "VNF";
break;
case 3:
nfapi_mode_str = "UE_STUB_PNF";
break;
default:
nfapi_mode_str = "<UNKNOWN NFAPI MODE>";
break;
}
printf("NFAPI MODE:%s\n", nfapi_mode_str);
// Panos: We should never enter here since we are always going to run with nfapi_mode=3
if (nfapi_mode==2) // VNF
wait_nfapi_init("main?");
printf("START MAIN THREADS\n");
// start the main threads
if (UE_flag == 1) {
int eMBMS_active = 0;
// Panos: Call init_UE_stub instead of init_UE as we are always on nfapi_mode=3
//phy_stub_ticking = (SF_ticking*)malloc(sizeof(SF_ticking));
init_timer_thread();
init_UE_stub(1,eMBMS_active,uecap_xer_in);
//init_UE(1,eMBMS_active,uecap_xer_in);
number_of_cards = 1;
if (nfapi_mode==3) // UE-STUB-PNF
{
wait_nfapi_init("main?");
}
/*for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
PHY_vars_UE_g[0][CC_id]->rf_map.card=0;
PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset;
}*/
}
// Panos: We should never enter this else case for nfapi_mode=3.
/*else {
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", single_thread_flag,wait_for_sync);
init_eNB(single_thread_flag,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);
if (RC.nb_RU >0) {
printf("Initializing RU threads\n");
init_RU(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+chain_offset;
}
}
config_sync_var=0;
if (nfapi_mode==1) // PNF
{
wait_nfapi_init("main?");
}
printf("wait RUs\n");
wait_RUs();
printf("ALL RUs READY!\n");
printf("RC.nb_RU:%d\n", RC.nb_RU);
// once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration)
printf("ALL RUs ready - init eNBs\n");
if (nfapi_mode != 1 && nfapi_mode != 2)
{
printf("Not NFAPI mode - call init_eNB_afterRU()\n");
init_eNB_afterRU();
}
else
{
printf("NFAPI mode - DO NOT call init_eNB_afterRU()\n");
}
printf("ALL RUs ready - ALL eNBs ready\n");
}*/
if (phy_test==0) {
if (UE_flag==1) {
printf("Filling UE band info\n");
fill_ue_band_info();
dl_phy_sync_success (0, 0, 0, 1);
}
}
// connect the TX/RX buffers
if (UE_flag==1) {
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
#ifdef OAI_USRP
UE[CC_id]->hw_timing_advance = timing_advance;
#else
UE[CC_id]->hw_timing_advance = 160;
#endif
}
// Panos: No need to call setup_ue_buffers() for nfapi_mode=3
/*if (setup_ue_buffers(UE,&openair0_cfg[0])!=0) {
printf("Error setting up eNB buffer\n");
exit(-1);
}*/
// Panos: Similar for nfapi_mode=3
/*if (input_fd) {
printf("Reading in from file to antenna buffer %d\n",0);
if (fread(UE[0]->common_vars.rxdata[0],
sizeof(int32_t),
frame_parms[0]->samples_per_tti*10,
input_fd) != frame_parms[0]->samples_per_tti*10)
printf("error reading from file\n");
}*/
//p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
} else {
printf("eNB mode\n");
}
printf("Sending sync to all threads\n");
pthread_mutex_lock(&sync_mutex);
sync_var=0;
pthread_cond_broadcast(&sync_cond);
pthread_mutex_unlock(&sync_mutex);
printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
end_configmodule();
printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
// wait for end of program
printf("TYPE <CTRL-C> TO TERMINATE\n");
//getchar();
#if defined(ENABLE_ITTI)
printf("Entering ITTI signals handler\n");
itti_wait_tasks_end();
printf("Returned from ITTI signal handler\n");
oai_exit=1;
printf("oai_exit=%d\n",oai_exit);
#else
while (oai_exit==0)
rt_sleep_ns(100000000ULL);
printf("Terminating application - oai_exit=%d\n",oai_exit);
#endif
// stop threads
#ifdef XFORMS
printf("waiting for XFORMS thread\n");
if (do_forms==1) {
pthread_join(forms_thread,&status);
fl_hide_form(form_stats->stats_form);
fl_free_form(form_stats->stats_form);
if (UE_flag==1) {
fl_hide_form(form_ue[0]->lte_phy_scope_ue);
fl_free_form(form_ue[0]->lte_phy_scope_ue);
} else {
fl_hide_form(form_stats_l2->stats_form);
fl_free_form(form_stats_l2->stats_form);
for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
fl_hide_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb);
fl_free_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb);
}
}
}
}
#endif
printf("stopping MODEM threads\n");
// cleanup
if (UE_flag == 1) {
} /*else {
stop_eNB(1);
}*/
pthread_cond_destroy(&sync_cond);
pthread_mutex_destroy(&sync_mutex);
pthread_cond_destroy(&nfapi_sync_cond);
pthread_mutex_destroy(&nfapi_sync_mutex);
// Panos: No RF in phy_stub mode: Exclude the following lines
// *** Handle per CC_id openair0
/*if (UE_flag==1) {
if (PHY_vars_UE_g[0][0]->rfdevice.trx_end_func)
PHY_vars_UE_g[0][0]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][0]->rfdevice);
}
else {
for(ru_id=0; ru_id<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);
if (RC.ru[ru_id]->ifdevice.trx_end_func)
RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
}
}*/
if (ouput_vcd)
VCD_SIGNAL_DUMPER_CLOSE();
if (opt_enabled == 1)
terminate_opt();
logClean();
return 0;
}
...@@ -101,7 +101,6 @@ unsigned short config_frames[4] = {2,9,11,13}; ...@@ -101,7 +101,6 @@ unsigned short config_frames[4] = {2,9,11,13};
#endif #endif
#include "lte-softmodem.h" #include "lte-softmodem.h"
#ifdef XFORMS #ifdef XFORMS
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0) // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
// at eNB 0, an UL scope for every UE // at eNB 0, an UL scope for every UE
...@@ -113,9 +112,18 @@ unsigned char scope_enb_num_ue = 2; ...@@ -113,9 +112,18 @@ unsigned char scope_enb_num_ue = 2;
static pthread_t forms_thread; //xforms static pthread_t forms_thread; //xforms
#endif //XFORMS #endif //XFORMS
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
uint8_t nfapi_mode = 0;
uint16_t sf_ahead=4;
pthread_cond_t sync_cond; pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex; pthread_mutex_t sync_mutex;
int sync_var=-1; //!< protected by mutex \ref sync_mutex. int sync_var=-1; //!< protected by mutex \ref sync_mutex.
int config_sync_var=-1;
uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
...@@ -205,6 +213,12 @@ uint64_t num_missed_slots=0; // counter for the number of missed slots ...@@ -205,6 +213,12 @@ uint64_t num_missed_slots=0; // counter for the number of missed slots
extern void reset_opp_meas(void); extern void reset_opp_meas(void);
extern void print_opp_meas(void); extern void print_opp_meas(void);
extern PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t UE_id,
uint8_t abstraction_flag);
extern void init_eNB_afterRU(void);
int transmission_mode=1; int transmission_mode=1;
...@@ -834,7 +848,7 @@ void init_openair0() { ...@@ -834,7 +848,7 @@ void init_openair0() {
void wait_RUs(void) { void wait_RUs(void) {
LOG_I(PHY,"Waiting for RUs to be configured ...\n"); LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
// wait for all RUs to be configured over fronthaul // wait for all RUs to be configured over fronthaul
pthread_mutex_lock(&RC.ru_mutex); pthread_mutex_lock(&RC.ru_mutex);
...@@ -843,6 +857,7 @@ void wait_RUs(void) { ...@@ -843,6 +857,7 @@ void wait_RUs(void) {
while (RC.ru_mask>0) { while (RC.ru_mask>0) {
pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex); pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
printf("RC.ru_mask:%02lx\n", RC.ru_mask);
} }
LOG_I(PHY,"RUs configured\n"); LOG_I(PHY,"RUs configured\n");
...@@ -856,18 +871,36 @@ void wait_eNBs(void) { ...@@ -856,18 +871,36 @@ void wait_eNBs(void) {
while (waiting==1) { while (waiting==1) {
printf("Waiting for eNB L1 instances to all get configured ... sleeping 500ms (nb_L1_inst %d)\n",RC.nb_L1_inst); printf("Waiting for eNB L1 instances to all get configured ... sleeping 500ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
usleep(500000); usleep(5000000);
waiting=0; waiting=0;
for (i=0;i<RC.nb_L1_inst;i++) for (i=0;i<RC.nb_L1_inst;i++) {
for (j=0;j<RC.nb_L1_CC[i];j++)
printf("RC.nb_L1_CC[%d]:%d\n", i, RC.nb_L1_CC[i]);
for (j=0;j<RC.nb_L1_CC[i];j++) {
if (RC.eNB[i][j]->configured==0) { if (RC.eNB[i][j]->configured==0) {
waiting=1; waiting=1;
break; break;
} }
}
}
} }
printf("eNB L1 are configured\n"); printf("eNB L1 are configured\n");
} }
static inline void wait_nfapi_init(char *thread_name) {
printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
pthread_mutex_lock( &nfapi_sync_mutex );
while (nfapi_sync_var<0)
pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
pthread_mutex_unlock(&nfapi_sync_mutex);
printf( "NFAPI: got sync (%s)\n", thread_name);
}
int main( int argc, char **argv ) int main( int argc, char **argv )
{ {
int i; int i;
...@@ -906,7 +939,6 @@ int main( int argc, char **argv ) ...@@ -906,7 +939,6 @@ int main( int argc, char **argv )
// set default parameters // set default parameters
if (UE_flag == 1) set_default_frame_parms(frame_parms); if (UE_flag == 1) set_default_frame_parms(frame_parms);
logInit(); logInit();
printf("Reading in command-line options\n"); printf("Reading in command-line options\n");
...@@ -969,6 +1001,7 @@ int main( int argc, char **argv ) ...@@ -969,6 +1001,7 @@ int main( int argc, char **argv )
log_set_instance_type (LOG_INSTANCE_ENB); log_set_instance_type (LOG_INSTANCE_ENB);
} }
printf("ITTI init\n");
itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file); itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
// initialize mscgen log after ITTI // initialize mscgen log after ITTI
...@@ -988,6 +1021,7 @@ int main( int argc, char **argv ) ...@@ -988,6 +1021,7 @@ int main( int argc, char **argv )
} }
#ifdef PDCP_USE_NETLINK #ifdef PDCP_USE_NETLINK
printf("PDCP netlink\n");
netlink_init(); netlink_init();
#if defined(PDCP_USE_NETLINK_QUEUES) #if defined(PDCP_USE_NETLINK_QUEUES)
pdcp_netlink_init(); pdcp_netlink_init();
...@@ -1021,6 +1055,7 @@ int main( int argc, char **argv ) ...@@ -1021,6 +1055,7 @@ int main( int argc, char **argv )
printf("Before CC \n");
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
...@@ -1084,6 +1119,7 @@ int main( int argc, char **argv ) ...@@ -1084,6 +1119,7 @@ int main( int argc, char **argv )
} }
} }
printf("Runtime table\n");
fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx); fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
cpuf=get_cpu_freq_GHz(); cpuf=get_cpu_freq_GHz();
...@@ -1091,6 +1127,7 @@ int main( int argc, char **argv ) ...@@ -1091,6 +1127,7 @@ int main( int argc, char **argv )
#ifndef DEADLINE_SCHEDULER #ifndef DEADLINE_SCHEDULER
printf("NO deadline scheduler\n");
/* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */ /* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */
cpu_set_t cpuset; cpu_set_t cpuset;
...@@ -1131,7 +1168,10 @@ int main( int argc, char **argv ) ...@@ -1131,7 +1168,10 @@ int main( int argc, char **argv )
#if defined(ENABLE_ITTI) #if defined(ENABLE_ITTI)
printf("ITTI enabled\n");
printf("UE_flag:%d\n", UE_flag);
printf("RC.nb_inst:%d\n", RC.nb_inst);
if ((UE_flag == 1)|| if ((UE_flag == 1)||
(RC.nb_inst > 0)) { (RC.nb_inst > 0)) {
...@@ -1157,9 +1197,6 @@ int main( int argc, char **argv ) ...@@ -1157,9 +1197,6 @@ int main( int argc, char **argv )
} }
} }
mlockall(MCL_CURRENT | MCL_FUTURE); mlockall(MCL_CURRENT | MCL_FUTURE);
pthread_cond_init(&sync_cond,NULL); pthread_cond_init(&sync_cond,NULL);
...@@ -1168,6 +1205,8 @@ int main( int argc, char **argv ) ...@@ -1168,6 +1205,8 @@ int main( int argc, char **argv )
#ifdef XFORMS #ifdef XFORMS
int UE_id; int UE_id;
printf("XFORMS\n");
if (do_forms==1) { if (do_forms==1) {
fl_initialize (&argc, argv, NULL, 0, 0); fl_initialize (&argc, argv, NULL, 0, 0);
...@@ -1224,8 +1263,36 @@ int main( int argc, char **argv ) ...@@ -1224,8 +1263,36 @@ int main( int argc, char **argv )
rt_sleep_ns(10*100000000ULL); rt_sleep_ns(10*100000000ULL);
if (nfapi_mode)
{
printf("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);
}
const char *nfapi_mode_str = "<UNKNOWN>";
switch(nfapi_mode)
{
case 0:
nfapi_mode_str = "MONOLITHIC";
break;
case 1:
nfapi_mode_str = "PNF";
break;
case 2:
nfapi_mode_str = "VNF";
break;
default:
nfapi_mode_str = "<UNKNOWN NFAPI MODE>";
break;
}
printf("NFAPI MODE:%s\n", nfapi_mode_str);
if (nfapi_mode==2) // VNF
wait_nfapi_init("main?");
printf("START MAIN THREADS\n");
// start the main threads // start the main threads
if (UE_flag == 1) { if (UE_flag == 1) {
...@@ -1240,15 +1307,18 @@ int main( int argc, char **argv ) ...@@ -1240,15 +1307,18 @@ int main( int argc, char **argv )
} }
else { else {
number_of_cards = 1; number_of_cards = 1;
printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
if (RC.nb_L1_inst > 0) { if (RC.nb_L1_inst > 0) {
printf("Initializing eNB threads\n"); printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", single_thread_flag,wait_for_sync);
init_eNB(single_thread_flag,wait_for_sync); init_eNB(single_thread_flag,wait_for_sync);
// for (inst=0;inst<RC.nb_L1_inst;inst++) // 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); // 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(); wait_eNBs();
printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
if (RC.nb_RU >0) { if (RC.nb_RU >0) {
printf("Initializing RU threads\n"); printf("Initializing RU threads\n");
init_RU(rf_config_file); init_RU(rf_config_file);
...@@ -1258,10 +1328,31 @@ int main( int argc, char **argv ) ...@@ -1258,10 +1328,31 @@ int main( int argc, char **argv )
} }
} }
config_sync_var=0;
if (nfapi_mode==1) // PNF
{
wait_nfapi_init("main?");
}
printf("wait RUs\n");
wait_RUs(); wait_RUs();
printf("ALL RUs READY!\n");
printf("RC.nb_RU:%d\n", RC.nb_RU);
// once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration) // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration)
init_eNB_afterRU(); printf("ALL RUs ready - init eNBs\n");
if (nfapi_mode != 1 && nfapi_mode != 2)
{
printf("Not NFAPI mode - call init_eNB_afterRU()\n");
init_eNB_afterRU();
}
else
{
printf("NFAPI mode - DO NOT call init_eNB_afterRU()\n");
}
printf("ALL RUs ready - ALL eNBs ready\n");
} }
...@@ -1295,38 +1386,35 @@ int main( int argc, char **argv ) ...@@ -1295,38 +1386,35 @@ int main( int argc, char **argv )
//p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX; //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
} else { } else {
printf("eNB mode\n");
} }
printf("Sending sync to all threads\n"); printf("Sending sync to all threads\n");
pthread_mutex_lock(&sync_mutex); pthread_mutex_lock(&sync_mutex);
sync_var=0; sync_var=0;
pthread_cond_broadcast(&sync_cond); pthread_cond_broadcast(&sync_cond);
pthread_mutex_unlock(&sync_mutex); pthread_mutex_unlock(&sync_mutex);
printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
end_configmodule(); end_configmodule();
printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
// wait for end of program // wait for end of program
printf("TYPE <CTRL-C> TO TERMINATE\n"); printf("TYPE <CTRL-C> TO TERMINATE\n");
//getchar(); //getchar();
#if defined(ENABLE_ITTI) #if defined(ENABLE_ITTI)
printf("Entering ITTI signals handler\n"); printf("Entering ITTI signals handler\n");
itti_wait_tasks_end(); itti_wait_tasks_end();
printf("Returned from ITTI signal handler\n");
oai_exit=1; oai_exit=1;
printf("oai_exit=%d\n",oai_exit);
#else #else
while (oai_exit==0) while (oai_exit==0)
rt_sleep_ns(100000000ULL); rt_sleep_ns(100000000ULL);
printf("Terminating application - oai_exit=%d\n",oai_exit);
#endif #endif
...@@ -1369,6 +1457,9 @@ int main( int argc, char **argv ) ...@@ -1369,6 +1457,9 @@ int main( int argc, char **argv )
pthread_cond_destroy(&sync_cond); pthread_cond_destroy(&sync_cond);
pthread_mutex_destroy(&sync_mutex); pthread_mutex_destroy(&sync_mutex);
pthread_cond_destroy(&nfapi_sync_cond);
pthread_mutex_destroy(&nfapi_sync_mutex);
// *** Handle per CC_id openair0 // *** Handle per CC_id openair0
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "LAYER2/MAC/defs.h" #include "LAYER2/MAC/defs.h"
#include "RRC/LITE/extern.h" #include "RRC/LITE/extern.h"
#endif #endif
#include "PHY_INTERFACE/phy_stub_UE.h"
#include "PHY_INTERFACE/extern.h" #include "PHY_INTERFACE/extern.h"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all #undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
...@@ -46,6 +47,8 @@ ...@@ -46,6 +47,8 @@
#include "SCHED/extern.h" #include "SCHED/extern.h"
#include "LAYER2/MAC/extern.h" #include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/proto.h" #include "LAYER2/MAC/proto.h"
//#include "openair2/PHY_INTERFACE/phy_stub_UE.h"
#include "UTIL/LOG/log_extern.h" #include "UTIL/LOG/log_extern.h"
#include "UTIL/OTG/otg_tx.h" #include "UTIL/OTG/otg_tx.h"
...@@ -57,6 +60,7 @@ ...@@ -57,6 +60,7 @@
#include "T.h" #include "T.h"
extern double cpuf; extern double cpuf;
extern uint8_t nfapi_mode;
#define FRAME_PERIOD 100000000ULL #define FRAME_PERIOD 100000000ULL
#define DAQ_PERIOD 66667ULL #define DAQ_PERIOD 66667ULL
...@@ -69,12 +73,20 @@ typedef enum { ...@@ -69,12 +73,20 @@ typedef enum {
} sync_mode_t; } sync_mode_t;
void init_UE_threads(int); void init_UE_threads(int);
void init_UE_threads_stub(int);
void *UE_thread(void *arg); void *UE_thread(void *arg);
void init_UE(int nb_inst,int,int); void init_UE(int nb_inst,int,int);
void init_UE_stub(int nb_inst,int,int);
extern void oai_subframe_ind(uint16_t sfn, uint16_t sf);
//extern int tx_req_UE_MAC1();
int32_t **rxdata; int32_t **rxdata;
int32_t **txdata; int32_t **txdata;
int timer_subframe;
int timer_frame;
SF_ticking *phy_stub_ticking;
#define KHz (1000UL) #define KHz (1000UL)
#define MHz (1000*KHz) #define MHz (1000*KHz)
...@@ -153,10 +165,15 @@ PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms, ...@@ -153,10 +165,15 @@ PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
ue->Mod_id = UE_id; ue->Mod_id = UE_id;
ue->mac_enabled = 1; ue->mac_enabled = 1;
// Panos: In phy_stub_UE (MAC-to-MAC) mode these init functions don't need to get called. Is this correct?
if (nfapi_mode!=3)
{
// initialize all signal buffers // initialize all signal buffers
init_lte_ue_signal(ue,1,abstraction_flag); init_lte_ue_signal(ue,1,abstraction_flag);
// intialize transport // intialize transport
init_lte_ue_transport(ue,abstraction_flag); init_lte_ue_transport(ue,abstraction_flag);
}
return(ue); return(ue);
} }
...@@ -249,6 +266,58 @@ void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in) { ...@@ -249,6 +266,58 @@ void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in) {
#endif #endif
} }
void init_UE_stub(int nb_inst,int eMBMS_active, int uecap_xer_in) {
PHY_VARS_UE *UE;
int inst;
//int ret;
LOG_I(PHY,"UE : Calling Layer 2 for initialization\n");
l2_init_ue(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
0,// cba_group_active
0); // HO flag
for (inst=0;inst<nb_inst;inst++) {
LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]);
PHY_vars_UE_g[inst][0] = init_ue_vars(NULL,inst,0);
LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
init_UE_threads_stub(inst);
UE = PHY_vars_UE_g[inst][0];
/*if (oaisim_flag == 0) {
ret = openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]);
if (ret !=0){
exit_fun("Error loading device library");
}
}*/
//UE->rfdevice.host_type = RAU_HOST;
// UE->rfdevice.type = NONE_DEV;
/*PHY_VARS_UE *UE = PHY_vars_UE_g[inst][0];
AssertFatal(0 == pthread_create(&UE->proc.pthread_ue,
&UE->proc.attr_ue,
UE_thread,
(void*)UE), "");*/
}
printf("UE threads created \n");
#if 0
#if defined(ENABLE_USE_MME)
extern volatile int start_UE;
while (start_UE == 0) {
sleep(1);
}
#endif
#endif
}
/*! /*!
* \brief This is the UE synchronize thread. * \brief This is the UE synchronize thread.
* It performs band scanning and synchonization. * It performs band scanning and synchonization.
...@@ -700,6 +769,204 @@ static void *UE_thread_rxn_txnp4(void *arg) { ...@@ -700,6 +769,204 @@ static void *UE_thread_rxn_txnp4(void *arg) {
return &UE_thread_rxtx_retval; return &UE_thread_rxtx_retval;
} }
/*!
* \brief This is the UE thread for RX subframe n and TX subframe n+4.
* This thread performs the phy_procedures_UE_RX() on every received slot.
* then, if TX is enabled it performs TX for n+4.
* \param arg is a pointer to a \ref PHY_VARS_UE structure.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
*/
static void *UE_phy_stub_thread_rxn_txnp4(void *arg) {
module_id_t Mod_id = 0;
static __thread int UE_thread_rxtx_retval;
struct rx_tx_thread_data *rtd = arg;
UE_rxtx_proc_t *proc = rtd->proc;
PHY_VARS_UE *UE = rtd->UE;
int ret;
// Panos: Call (Sched_Rsp_t) get_nfapi_sched_response(UE->Mod_ID) to get all
//sched_response config messages which concern the specific UE. Inside this
//function we should somehow make the translation of rnti to Mod_ID.
//proc->instance_cnt_rxtx=-1;
phy_stub_ticking->ticking_var = -1;
proc->subframe_rx=proc->sub_frame_start;
char threadname[256];
sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start);
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.one != -1 )
CPU_SET(threads.one, &cpuset);
if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.two != -1 )
CPU_SET(threads.two, &cpuset);
if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.three != -1 )
CPU_SET(threads.three, &cpuset);
//CPU_SET(threads.three, &cpuset);
init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
threadname);
while (!oai_exit) {
if (pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) != 0) {
LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
exit_fun("nothing to add");
}
while (phy_stub_ticking->ticking_var < 0) {
// most of the time, the thread is waiting here
//pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );
pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking);
}
if (pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) != 0) {
LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
exit_fun("nothing to add");
}
proc->subframe_rx=timer_subframe;
proc->frame_rx = timer_frame;
proc->subframe_tx=(timer_subframe+4)%10;
proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5?1:0);
// Panos: Guessing that the next 4 lines are not needed for the phy_stub mode.
/*initRefTimes(t2);
initRefTimes(t3);
pickTime(current);
updateTimes(proc->gotIQs, &t2, 10000, "Delay to wake up UE_Thread_Rx (case 2)");*/
// Process Rx data for one sub-frame
lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx);
if ((sf_type == SF_DL) ||
(UE->frame_parms.frame_type == FDD) ||
(sf_type == SF_S)) {
if (UE->frame_parms.frame_type == TDD) {
LOG_D(PHY, "%s,TDD%d,%s: calling UE_RX\n",
threadname,
UE->frame_parms.tdd_config,
(sf_type==SF_DL? "SF_DL" :
(sf_type==SF_UL? "SF_UL" :
(sf_type==SF_S ? "SF_S" : "UNKNOWN_SF_TYPE"))));
} else {
LOG_D(PHY, "%s,%s,%s: calling UE_RX\n",
threadname,
(UE->frame_parms.frame_type==FDD? "FDD":
(UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")),
(sf_type==SF_DL? "SF_DL" :
(sf_type==SF_UL? "SF_UL" :
(sf_type==SF_S ? "SF_S" : "UNKNOWN_SF_TYPE"))));
}
/*
#ifdef UE_SLOT_PARALLELISATION
phy_procedures_slot_parallelization_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
#else
*/
// Panos: Substitute call to phy_procedures Rx with call to phy_stub functions in order to trigger
// UE Rx procedures directly at the MAC layer, based on the received nfapi requests from the vnf (eNB).
// Hardcode Mod_id for now. Will be changed later.
// Panos: is this the right place to call oai_subframe_indication to invoke p7 nfapi callbacks here?
oai_subframe_ind(proc->frame_rx, proc->subframe_rx);
if(UE_mac_inst[Mod_id].tx_req!= NULL)
tx_req_UE_MAC(UE_mac_inst[Mod_id].tx_req);
if(UE_mac_inst[Mod_id].dl_config_req!= NULL)
dl_config_req_UE_MAC(UE_mac_inst[Mod_id].dl_config_req);
if(UE_mac_inst[Mod_id].hi_dci0_req!= NULL)
hi_dci0_req_UE_MAC(UE_mac_inst[Mod_id].hi_dci0_req);
//#endif
}
#if UE_TIMING_TRACE
start_meas(&UE->generic_stat);
#endif
if (UE->mac_enabled==1) {
ret = ue_scheduler(UE->Mod_id,
proc->frame_rx,
proc->subframe_rx,
proc->frame_tx,
proc->subframe_tx,
subframe_select(&UE->frame_parms,proc->subframe_tx),
0,
0/*FIXME CC_id*/);
if ( ret != CONNECTION_OK) {
char *txt;
switch (ret) {
case CONNECTION_LOST:
txt="RRC Connection lost, returning to PRACH";
break;
case PHY_RESYNCH:
txt="RRC Connection lost, trying to resynch";
break;
case RESYNCH:
txt="return to PRACH and perform a contention-free access";
break;
default:
txt="UNKNOWN RETURN CODE";
};
LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
UE->Mod_id, proc->frame_rx, proc->subframe_tx,txt );
}
}
#if UE_TIMING_TRACE
stop_meas(&UE->generic_stat);
#endif
// Prepare the future Tx data
if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
(UE->frame_parms.frame_type == FDD) )
if (UE->mode != loop_through_memory){
// Panos: Substitute call to phy_procedures Tx with call to phy_stub functions in order to trigger
// UE Tx procedures directly at the MAC layer, based on the received ul_config requests from the vnf (eNB).
// Generate UL_indications which corresponf to UL traffic.
if(UE_mac_inst[Mod_id].ul_config_req!= NULL){
ul_config_req_UE_MAC(UE_mac_inst[Mod_id].ul_config_req);
UL_indication(UL_INFO);
}
}
/*if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) &&
(UE->frame_parms.frame_type == TDD))
if (UE->mode != loop_through_memory)
phy_procedures_UE_S_TX(UE,0,0,no_relay);
updateTimes(current, &t3, 10000, "Delay to process sub-frame (case 3)");*/
//if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
if (pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) != 0) {
LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
exit_fun("noting to add");
}
//proc->instance_cnt_rxtx--;
phy_stub_ticking->ticking_var--;
//if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
if (pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) != 0) {
LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" );
exit_fun("noting to add");
}
}
// thread finished
free(arg);
return &UE_thread_rxtx_retval;
}
/*! /*!
* \brief This is the main UE thread. * \brief This is the main UE thread.
* This thread controls the other three UE threads: * This thread controls the other three UE threads:
...@@ -740,7 +1007,7 @@ void *UE_thread(void *arg) { ...@@ -740,7 +1007,7 @@ void *UE_thread(void *arg) {
int sub_frame=-1; int sub_frame=-1;
//int cumulated_shift=0; //int cumulated_shift=0;
while (!oai_exit) { while (!oai_exit) {
AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
int instance_cnt_synch = UE->proc.instance_cnt_synch; int instance_cnt_synch = UE->proc.instance_cnt_synch;
...@@ -951,6 +1218,7 @@ void *UE_thread(void *arg) { ...@@ -951,6 +1218,7 @@ void *UE_thread(void *arg) {
return NULL; return NULL;
} }
/*! /*!
* \brief Initialize the UE theads. * \brief Initialize the UE theads.
* Creates the UE threads: * Creates the UE threads:
...@@ -1008,6 +1276,69 @@ void init_UE_threads(int inst) { ...@@ -1008,6 +1276,69 @@ void init_UE_threads(int inst) {
} }
/*!
* \brief Initialize the UE theads.
* Creates the UE threads:
* - UE_thread_rxtx0
* - UE_thread_synch
* - UE_thread_fep_slot0
* - UE_thread_fep_slot1
* - UE_thread_dlsch_proc_slot0
* - UE_thread_dlsch_proc_slot1
* and the locking between them.
*/
void init_UE_threads_stub(int inst) {
struct rx_tx_thread_data *rtd;
PHY_VARS_UE *UE;
AssertFatal(PHY_vars_UE_g!=NULL,"PHY_vars_UE_g is NULL\n");
AssertFatal(PHY_vars_UE_g[inst]!=NULL,"PHY_vars_UE_g[inst] is NULL\n");
AssertFatal(PHY_vars_UE_g[inst][0]!=NULL,"PHY_vars_UE_g[inst][0] is NULL\n");
UE = PHY_vars_UE_g[inst][0];
pthread_attr_init (&UE->proc.attr_ue);
pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN);
// Panos: Don't need synch for phy_stub mode
//pthread_mutex_init(&UE->proc.mutex_synch,NULL);
//pthread_cond_init(&UE->proc.cond_synch,NULL);
// the threads are not yet active, therefore access is allowed without locking
// Panos: In phy_stub_UE mode due to less heavy processing operations we don't need two threads
//int nb_threads=RX_NB_TH;
int nb_threads=1;
for (int i=0; i<nb_threads; i++) {
rtd = calloc(1, sizeof(struct rx_tx_thread_data));
if (rtd == NULL) abort();
rtd->UE = UE;
rtd->proc = &UE->proc.proc_rxtx[i];
pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL);
pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL);
UE->proc.proc_rxtx[i].sub_frame_start=i;
UE->proc.proc_rxtx[i].sub_frame_step=nb_threads;
printf("Init_UE_threads rtd %d proc %d nb_threads %d i %d\n",rtd->proc->sub_frame_start, UE->proc.proc_rxtx[i].sub_frame_start,nb_threads, i);
pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_phy_stub_thread_rxn_txnp4, rtd);
/*
#ifdef UE_SLOT_PARALLELISATION
//pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot0_dl_processing,NULL);
//pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot0_dl_processing,NULL);
//pthread_create(&UE->proc.proc_rxtx[i].pthread_slot0_dl_processing,NULL,UE_thread_slot0_dl_processing, rtd);
pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot1_dl_processing,NULL);
pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot1_dl_processing,NULL);
pthread_create(&UE->proc.proc_rxtx[i].pthread_slot1_dl_processing,NULL,UE_thread_slot1_dl_processing, rtd);
#endif*/
}
// Panos: Remove thread for UE_sync in phy_stub_UE mode.
//pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE);
}
#ifdef OPENAIR2 #ifdef OPENAIR2
void fill_ue_band_info(void) { void fill_ue_band_info(void) {
...@@ -1078,3 +1409,65 @@ int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg) ...@@ -1078,3 +1409,65 @@ int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg)
return 0; return 0;
} }
// Panos: This timer thread is used only in the phy_sub mode as an independent timer
// which will be ticking and provide the SFN/SF values that will be used from the UE threads
// playing the role of nfapi-pnf.
static void* timer_thread( void* param ) {
timer_subframe =9;
timer_frame =1023;
//phy_stub_ticking = (SF_ticking*)malloc(sizeof(SF_ticking));
phy_stub_ticking->ticking_var = -1;
wait_sync("timer_thread");
//pthread_mutex_init(&phy_stub_ticking->mutex_ticking,NULL);
//pthread_cond_init(&phy_stub_ticking->cond_ticking,NULL);
while (!oai_exit) {
usleep(1000);
// these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
// They are set on the first rx/tx in the underly FH routines.
if (timer_subframe==9) {
timer_subframe=0;
timer_frame++;
timer_frame&=1023;
} else {
timer_subframe++;
}
//AssertFatal( 0 == pthread_cond_signal(&phy_stub_ticking->cond_ticking), "");
AssertFatal(pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) ==0,"");
phy_stub_ticking->ticking_var++;
// This should probably be a call to pthread_cond_broadcast when we introduce support for multiple UEs (threads)
if(phy_stub_ticking->ticking_var == 0) {
if (pthread_cond_signal(&phy_stub_ticking->cond_ticking) != 0) {
//LOG_E( PHY, "[SCHED][UE %d] ERROR pthread_cond_signal for UE RX thread\n", UE->Mod_id);
LOG_E( PHY, "timer_thread ERROR pthread_cond_signal for UE_thread\n");
exit_fun("nothing to add");
}
}
AssertFatal(pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) ==0,"");
//UE->proc.ticking_var++;
// pthread_cond_signal() //Send signal to ue_thread()?
// We also need to somehow pass the information of SFN/SF
}
free(phy_stub_ticking);
pthread_cond_destroy(&phy_stub_ticking->cond_ticking);
pthread_mutex_destroy(&phy_stub_ticking->mutex_ticking);
return 0;
}
int init_timer_thread(void) {
phy_stub_ticking = (SF_ticking*)malloc(sizeof(SF_ticking));
pthread_mutex_init(&phy_stub_ticking->mutex_ticking,NULL);
pthread_cond_init(&phy_stub_ticking->cond_ticking,NULL);
pthread_create(phy_stub_ticking->pthread_timer, NULL, &timer_thread, NULL);
return 0;
}
[*]
[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
[*] Tue Jul 25 20:26:12 2017
[*]
[dumpfile] "/tmp/openair_dump_eNB.vcd"
[dumpfile_mtime] "Tue Jul 25 20:11:55 2017"
[dumpfile_size] 19201475
[savefile] "/home/papillon/openairinterface5g/targets/RT/USER/eNB_usrp.gtkw"
[timestart] 29023604000
[size] 1236 578
[pos] 309 0
*-20.793451 29026062100 -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] 386
[signals_width] 262
[sst_expanded] 1
[sst_vpaned_height] 146
@28
functions.trx_read
functions.trx_write
@24
variables.trx_ts[63:0]
variables.trx_tst[63:0]
@25
variables.frame_number_RX0_RU[63:0]
variables.subframe_number_RX0_RU[63:0]
@25
variables.frame_number_TX0_RU[63:0]
variables.subframe_number_TX0_RU[63:0]
@24
functions.phy_procedures_ru_feprx0
functions.phy_procedures_ru_feprx1
functions.phy_procedures_eNb_rx_uespec0
functions.phy_procedures_eNb_tx0
functions.eNB_thread_rxtx1
functions.phy_enb_prach_rx
functions.phy_enb_rs_tx
functions.phy_enb_pdcch_tx
functions.nfapi_subframe
functions.generate_pcfich
functions.generate_dci0
functions.pdcch_scrambling
functions.pdcch_modulation
functions.pdcch_interleaving
functions.pdcch_tx
functions.generate_dlsch
functions.generate_phich
functions.udp_enb_task
functions.phy_procedures_ru_feptx_ofdm0
functions.phy_procedures_ru_feptx_ofdm1
functions.phy_procedures_ru_feptx_prec0
functions.phy_procedures_ru_feptx_prec1
functions.phy_enb_prach_rx
[pattern_trace] 1
[pattern_trace] 0
File added