git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5414 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
+204
-12
@@ -252,6 +252,8 @@ static int mbox_bounds[20] = {8,16,24,30,38,46,54,60,68,7
|
|||||||
|
|
||||||
static LTE_DL_FRAME_PARMS *frame_parms;
|
static LTE_DL_FRAME_PARMS *frame_parms;
|
||||||
|
|
||||||
|
int multi_thread=0;
|
||||||
|
|
||||||
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq)
|
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq)
|
||||||
{
|
{
|
||||||
return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
|
return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
|
||||||
@@ -623,7 +625,183 @@ void *l2l1_task(void *arg)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This is the main eNB thread. It gets woken up by the kernel driver using the RTAI message mechanism (rt_send and rt_receive). */
|
static void * eNB_proc_thread(void *param) {
|
||||||
|
|
||||||
|
//unsigned long cpuid;
|
||||||
|
eNB_proc_t *proc = (eNB_proc_t*)param;
|
||||||
|
int i,tx_offset;
|
||||||
|
int next_slot,last_slot;
|
||||||
|
RTIME time_in,time_out;
|
||||||
|
#ifdef RTAI
|
||||||
|
RT_TASK *task;
|
||||||
|
char task_name[8];
|
||||||
|
#endif
|
||||||
|
int dummy_tx_b[7680*4] __attribute__((aligned(16)));
|
||||||
|
unsigned int aa,slot_offset,slot_offset_F,slot_offset_F2;
|
||||||
|
|
||||||
|
#ifdef RTAI
|
||||||
|
sprintf(task_name,"eNB_proc %d",proc->subframe);
|
||||||
|
task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);
|
||||||
|
|
||||||
|
if (task==NULL) {
|
||||||
|
LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc thread_index %d (%s)!!!!\n",proc->subframe,task_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG_I(PHY,"[SCHED][eNB] dlsch_thread for process %d started with id %p\n",
|
||||||
|
proc->subframe,
|
||||||
|
task);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mlockall(MCL_CURRENT | MCL_FUTURE);
|
||||||
|
|
||||||
|
//rt_set_runnable_on_cpuid(task,1);
|
||||||
|
//cpuid = rtai_cpuid();
|
||||||
|
|
||||||
|
#ifdef HARD_RT
|
||||||
|
rt_make_hard_real_time();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
last_slot = ((proc->subframe<<1)-1)%20;
|
||||||
|
next_slot = ((proc->subframe<<1)+1)%20;
|
||||||
|
|
||||||
|
while (!oai_exit){
|
||||||
|
|
||||||
|
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC0+proc->subframe,0);
|
||||||
|
if (pthread_mutex_lock(&proc->mutex) != 0) {
|
||||||
|
LOG_E(PHY,"[SCHED][eNB] error locking mutex for eNB proc %d\n",proc->subframe);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
while (proc->instance_cnt < 0) {
|
||||||
|
pthread_cond_wait(&proc->cond,&proc->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_mutex_unlock(&proc->mutex) != 0) {
|
||||||
|
LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB proc %d\n",proc->subframe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC0+proc->subframe,1);
|
||||||
|
if (oai_exit) break;
|
||||||
|
|
||||||
|
if ((((PHY_vars_eNB_g[0]->lte_frame_parms.frame_type == TDD)&&(subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_DL))||
|
||||||
|
(PHY_vars_eNB_g[0]->lte_frame_parms.frame_type == FDD))) {
|
||||||
|
#ifdef Rel10
|
||||||
|
if (phy_procedures_RN_eNB_TX(last_slot, next_slot, no_relay) != 0 )
|
||||||
|
#endif
|
||||||
|
phy_procedures_eNB_TX(next_slot,PHY_vars_eNB_g[0],0,no_relay,NULL);
|
||||||
|
}
|
||||||
|
if ((((PHY_vars_eNB_g[0]->lte_frame_parms.frame_type == TDD )&&(subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,last_slot>>1)==SF_UL)) ||
|
||||||
|
(PHY_vars_eNB_g[0]->lte_frame_parms.frame_type == FDD))){
|
||||||
|
phy_procedures_eNB_RX(last_slot,PHY_vars_eNB_g[0],0,no_relay);
|
||||||
|
}
|
||||||
|
if ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_S)) {
|
||||||
|
#ifdef Rel10
|
||||||
|
if (phy_procedures_RN_eNB_TX(last_slot, next_slot, no_relay) != 0 )
|
||||||
|
#endif
|
||||||
|
phy_procedures_eNB_TX(next_slot,PHY_vars_eNB_g[0],0,no_relay,NULL);
|
||||||
|
}
|
||||||
|
if ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,last_slot>>1)==SF_S)){
|
||||||
|
phy_procedures_eNB_S_RX(last_slot,PHY_vars_eNB_g[0],0,no_relay);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
slot_offset_F = (next_slot)*
|
||||||
|
(PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size)*
|
||||||
|
((PHY_vars_eNB_g[0]->lte_frame_parms.Ncp==1) ? 6 : 7);
|
||||||
|
slot_offset = (next_slot)*
|
||||||
|
(PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti>>1);
|
||||||
|
slot_offset_F2 = (next_slot+1)*
|
||||||
|
(PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size)*
|
||||||
|
((PHY_vars_eNB_g[0]->lte_frame_parms.Ncp==1) ? 6 : 7);
|
||||||
|
|
||||||
|
if ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_DL)||
|
||||||
|
((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_S))) {
|
||||||
|
// LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot);
|
||||||
|
|
||||||
|
for (aa=0; aa<PHY_vars_eNB_g[0]->lte_frame_parms.nb_antennas_tx; aa++) {
|
||||||
|
if (PHY_vars_eNB_g[0]->lte_frame_parms.Ncp == 1) {
|
||||||
|
PHY_ofdm_mod(&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F],
|
||||||
|
dummy_tx_b,
|
||||||
|
PHY_vars_eNB_g[0]->lte_frame_parms.log2_symbol_size,
|
||||||
|
6,
|
||||||
|
PHY_vars_eNB_g[0]->lte_frame_parms.nb_prefix_samples,
|
||||||
|
PHY_vars_eNB_g[0]->lte_frame_parms.twiddle_ifft,
|
||||||
|
PHY_vars_eNB_g[0]->lte_frame_parms.rev,
|
||||||
|
CYCLIC_PREFIX);
|
||||||
|
PHY_ofdm_mod(&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F2],
|
||||||
|
dummy_tx_b+(PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti>>1),
|
||||||
|
PHY_vars_eNB_g[0]->lte_frame_parms.log2_symbol_size,
|
||||||
|
6,
|
||||||
|
PHY_vars_eNB_g[0]->lte_frame_parms.nb_prefix_samples,
|
||||||
|
PHY_vars_eNB_g[0]->lte_frame_parms.twiddle_ifft,
|
||||||
|
PHY_vars_eNB_g[0]->lte_frame_parms.rev,
|
||||||
|
CYCLIC_PREFIX);
|
||||||
|
}
|
||||||
|
#ifdef EXMIMO
|
||||||
|
for (i=0; i<PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti; i++) {
|
||||||
|
tx_offset = (int)slot_offset+time_offset[aa]+i;
|
||||||
|
if (tx_offset<0)
|
||||||
|
tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti;
|
||||||
|
if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti))
|
||||||
|
tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti;
|
||||||
|
((short*)&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]=
|
||||||
|
((short*)dummy_tx_b)[2*i]<<4;
|
||||||
|
((short*)&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]=
|
||||||
|
((short*)dummy_tx_b)[2*i+1]<<4;
|
||||||
|
}
|
||||||
|
#endif //EXMIMO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pthread_mutex_lock(&proc->mutex) != 0) {
|
||||||
|
msg("[openair][SCHED][eNB] error locking mutex for eNB proc %d\n",proc->subframe);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
proc->instance_cnt--;
|
||||||
|
|
||||||
|
if (pthread_mutex_unlock(&proc->mutex) != 0) {
|
||||||
|
msg("[openair][SCHED][eNB] error unlocking mutex for eNB proc %d\n",proc->subframe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HARD_RT
|
||||||
|
rt_make_soft_real_time();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void init_eNB_proc() {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0;i<10;i++) {
|
||||||
|
PHY_vars_eNB_g[0]->proc[i].instance_cnt=0;
|
||||||
|
PHY_vars_eNB_g[0]->proc[i].subframe=i;
|
||||||
|
pthread_mutex_init(&PHY_vars_eNB_g[0]->proc[i].mutex,NULL);
|
||||||
|
pthread_cond_init(&PHY_vars_eNB_g[0]->proc[i].cond,NULL);
|
||||||
|
pthread_create(&PHY_vars_eNB_g[0]->proc[i].pthread,NULL,eNB_proc_thread,(void*)&PHY_vars_eNB_g[0]->proc[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kill_eNB_proc() {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0;i<10;i++) {
|
||||||
|
pthread_join(PHY_vars_eNB_g[0]->proc[i].pthread,NULL);
|
||||||
|
pthread_mutex_destroy(&PHY_vars_eNB_g[0]->proc[i].mutex);
|
||||||
|
pthread_cond_destroy(&PHY_vars_eNB_g[0]->proc[i].cond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* This is the main eNB thread. */
|
||||||
static void *eNB_thread(void *arg)
|
static void *eNB_thread(void *arg)
|
||||||
{
|
{
|
||||||
#ifdef RTAI
|
#ifdef RTAI
|
||||||
@@ -638,6 +816,7 @@ static void *eNB_thread(void *arg)
|
|||||||
int mbox_target=0,mbox_current=0;
|
int mbox_target=0,mbox_current=0;
|
||||||
int i,ret;
|
int i,ret;
|
||||||
int tx_offset;
|
int tx_offset;
|
||||||
|
int sf;
|
||||||
|
|
||||||
#if defined(ENABLE_ITTI)
|
#if defined(ENABLE_ITTI)
|
||||||
/* Wait for eNB application initialization to be complete (eNB registration to MME) */
|
/* Wait for eNB application initialization to be complete (eNB registration to MME) */
|
||||||
@@ -726,7 +905,7 @@ static void *eNB_thread(void *arg)
|
|||||||
last_slot = (slot)%LTE_SLOTS_PER_FRAME;
|
last_slot = (slot)%LTE_SLOTS_PER_FRAME;
|
||||||
if (last_slot <0)
|
if (last_slot <0)
|
||||||
last_slot+=20;
|
last_slot+=20;
|
||||||
next_slot = (slot+3)%LTE_SLOTS_PER_FRAME;
|
next_slot = (slot+2)%LTE_SLOTS_PER_FRAME;
|
||||||
|
|
||||||
//PHY_vars_eNB_g[0]->frame = frame;
|
//PHY_vars_eNB_g[0]->frame = frame;
|
||||||
if (frame>5)
|
if (frame>5)
|
||||||
@@ -763,15 +942,15 @@ static void *eNB_thread(void *arg)
|
|||||||
|
|
||||||
if (fs4_test==0)
|
if (fs4_test==0)
|
||||||
{
|
{
|
||||||
|
if (multi_thread == 0) {
|
||||||
phy_procedures_eNB_lte (last_slot, next_slot, PHY_vars_eNB_g[0], 0, no_relay,NULL);
|
phy_procedures_eNB_lte (last_slot, next_slot, PHY_vars_eNB_g[0], 0, no_relay,NULL);
|
||||||
#ifndef IFFT_FPGA
|
|
||||||
slot_offset_F = (next_slot)*
|
slot_offset_F = (next_slot)*
|
||||||
(PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size)*
|
(PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size)*
|
||||||
((PHY_vars_eNB_g[0]->lte_frame_parms.Ncp==1) ? 6 : 7);
|
((PHY_vars_eNB_g[0]->lte_frame_parms.Ncp==1) ? 6 : 7);
|
||||||
slot_offset = (next_slot)*
|
slot_offset = (next_slot)*
|
||||||
(PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti>>1);
|
(PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti>>1);
|
||||||
if ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_DL)||
|
if ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_DL)||
|
||||||
((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_S)&&((next_slot&1)==0)))
|
((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_S)))
|
||||||
{
|
{
|
||||||
// LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot);
|
// LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot);
|
||||||
|
|
||||||
@@ -820,14 +999,22 @@ static void *eNB_thread(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else { // multi-thread > 0
|
||||||
|
|
||||||
#endif //IFFT_FPGA
|
if ((slot&1) == 0) {
|
||||||
/*
|
sf = (slot<<1)+1;
|
||||||
if (frame%100==0)
|
if (PHY_vars_eNB_g[0]->proc[sf].instance_cnt == 0) {
|
||||||
LOG_D(HW,"hw_slot %d (after): DAQ_MBOX %d\n",hw_slot,DAQ_MBOX[0]);
|
if (pthread_cond_signal(&PHY_vars_eNB_g[0]->proc[sf].cond) != 0) {
|
||||||
*/
|
LOG_E(PHY,"[eNB] ERROR pthread_cond_signal for eNB proc %d\n",sf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG_W(PHY,"[eNB] Frame %d, eNB proc %d busy!!\n",PHY_vars_eNB_g[0]->frame,sf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if ((slot%2000)<10)
|
if ((slot%2000)<10)
|
||||||
LOG_D(HW,"fun0: doing very hard work\n");
|
LOG_D(HW,"fun0: doing very hard work\n");
|
||||||
@@ -1122,7 +1309,7 @@ static void get_options (int argc, char **argv)
|
|||||||
{"no-L2-connect", no_argument, NULL, LONG_OPTION_NO_L2_CONNECT},
|
{"no-L2-connect", no_argument, NULL, LONG_OPTION_NO_L2_CONNECT},
|
||||||
{NULL, 0, NULL, 0}};
|
{NULL, 0, NULL, 0}};
|
||||||
|
|
||||||
while ((c = getopt_long (argc, argv, "C:dF:K:qO:ST:UVR",long_options,NULL)) != -1)
|
while ((c = getopt_long (argc, argv, "C:dF:K:qO:ST:UVRM",long_options,NULL)) != -1)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
@@ -1156,7 +1343,9 @@ static void get_options (int argc, char **argv)
|
|||||||
case LONG_OPTION_NO_L2_CONNECT:
|
case LONG_OPTION_NO_L2_CONNECT:
|
||||||
mode = no_L2_connect;
|
mode = no_L2_connect;
|
||||||
break;
|
break;
|
||||||
|
case 'M':
|
||||||
|
multi_thread=1;
|
||||||
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
downlink_frequency[0] = atof(optarg); // Use float to avoid issue with frequency over 2^31.
|
downlink_frequency[0] = atof(optarg); // Use float to avoid issue with frequency over 2^31.
|
||||||
downlink_frequency[1] = downlink_frequency[0];
|
downlink_frequency[1] = downlink_frequency[0];
|
||||||
@@ -1983,6 +2172,9 @@ int main(int argc, char **argv) {
|
|||||||
#ifdef ULSCH_THREAD
|
#ifdef ULSCH_THREAD
|
||||||
init_ulsch_threads();
|
init_ulsch_threads();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
init_eNB_proc();
|
||||||
|
|
||||||
printf("eNB threads created\n");
|
printf("eNB threads created\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user