From 70da4b5902a7ef2a0d2ee9b6677276a65313c3f7 Mon Sep 17 00:00:00 2001 From: Xu Bo Date: Mon, 22 Jan 2018 03:59:04 +0000 Subject: [PATCH 1/2] modify pre_scd thread and add phy_tx and rf_tx thread --- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 90 +++++- openair1/PHY/LTE_TRANSPORT/defs.h | 28 +- openair1/PHY/LTE_TRANSPORT/dlsch_coding.c | 5 + openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c | 18 ++ openair1/PHY/defs.h | 36 ++- openair1/SCHED/fapi_l1.c | 28 ++ openair1/SCHED/phy_procedures_lte_eNb.c | 15 +- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 16 + openair2/LAYER2/MAC/extern.h | 4 - openair2/LAYER2/MAC/pre_processor.c | 134 ++------- openair2/LAYER2/MAC/vars.h | 4 - targets/RT/USER/lte-enb.c | 77 +---- targets/RT/USER/lte-ru.c | 280 +++++++++++++++++- targets/RT/USER/lte-softmodem.c | 5 + targets/RT/USER/lte-softmodem.h | 3 + 15 files changed, 513 insertions(+), 230 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 6fce45ab1e..459d321b3e 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -1071,7 +1071,11 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC_t *dci } dlsch0_harq->ndi = rel8->new_data_indicator_1; +#ifdef UE_EXPANSION + dlsch0->active[subframe] = 1; +#else dlsch0->active = 1; +#endif if (rel8->rnti_type == 2) dlsch0_harq->round = 0; LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n",rel8->harq_process,dlsch0->harq_mask,dlsch0_harq->round, @@ -1237,7 +1241,11 @@ LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n" dlsch0_harq->Qm = 2; dlsch0_harq->TBS = TBStable[I_mcs][NPRB-1]; dlsch0->harq_ids[subframe] = rel8->harq_process; +#ifdef UE_EXPANSION + dlsch0->active[subframe] = 1; +#else dlsch0->active = 1; +#endif dlsch0->rnti = rel8->rnti; dlsch0->harq_ids[subframe] = rel8->harq_process; if (dlsch0_harq->round == 0) @@ -1251,7 +1259,11 @@ LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n" case NFAPI_DL_DCI_FORMAT_1: dci_alloc->format = format1; +#ifdef UE_EXPANSION + dlsch0->active[subframe] = 1; +#else dlsch0->active = 1; +#endif LOG_D(PHY,"Frame %d, Subframe %d: Programming DLSCH for Format 1 DCI, harq_pid %d\n",proc->frame_tx,subframe,rel8->harq_process); @@ -1388,7 +1400,11 @@ LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n" dlsch0_harq->dl_power_off = 1; +#ifdef UE_EXPANSION + dlsch0->active[subframe] = 1; +#else dlsch0->active = 1; +#endif @@ -1591,19 +1607,32 @@ LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n" // assume both TBs are active dlsch0_harq->Nl = 1; dlsch1_harq->Nl = 1; +#ifdef UE_EXPANSION + dlsch0->active[subframe] = 1; + dlsch1->active[subframe] = 1; +#else dlsch0->active = 1; dlsch1->active = 1; +#endif dlsch0->harq_mask |= (1<harq_process); dlsch1->harq_mask |= (1<harq_process); // check if either TB is disabled (see 36-213 V11.3 Section ) if ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0)) { +#ifdef UE_EXPANSION + dlsch0->active[subframe] = 0; +#else dlsch0->active = 0; +#endif dlsch0->harq_mask &= ~(1<harq_process); } if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) { +#ifdef UE_EXPANSION + dlsch1->active[subframe]= 0; +#else dlsch1->active = 0; +#endif dlsch1->harq_mask &= ~(1<harq_process); } @@ -1615,8 +1644,11 @@ LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n" dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; dlsch1_harq->TBS = TBStable[get_I_TBS(dlsch1_harq->mcs)][dlsch0_harq->nb_rb-1]; +#ifdef UE_EXPANSION + if ((dlsch0->active[subframe]==1) && (dlsch1->active[subframe]==1)) { +#else if ((dlsch0->active==1) && (dlsch1->active==1)) { - +#endif dlsch0_harq->mimo_mode = LARGE_CDD; dlsch1_harq->mimo_mode = LARGE_CDD; dlsch0_harq->dl_power_off = 1; @@ -1626,7 +1658,11 @@ LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n" dlsch1_harq->mimo_mode = ALAMOUTI; } } else if (fp->nb_antenna_ports_eNB == 4) { // 4 antenna case +#ifdef UE_EXPANSION + if ((dlsch0->active[subframe]==1) && (dlsch1->active[subframe]==1)) { +#else if ((dlsch0->active==1) && (dlsch1->active==1)) { +#endif switch (rel8->precoding_information) { case 0: // one layer per transport block dlsch0_harq->mimo_mode = LARGE_CDD; @@ -1666,7 +1702,11 @@ LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n" LOG_E(PHY,"Illegal value (3) for TPMI in Format 2A DCI\n"); break; } +#ifdef UE_EXPANSION + } else if (dlsch0->active[subframe] == 1) { +#else } else if (dlsch0->active == 1) { +#endif switch (rel8->precoding_information) { case 0: // one layer per transport block dlsch0_harq->mimo_mode = ALAMOUTI; @@ -1686,7 +1726,11 @@ LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n" LOG_E(PHY,"Illegal value %d for TPMI in Format 2A DCI with one transport block enabled\n",rel8->precoding_information); break; } +#ifdef UE_EXPANSION + } else if (dlsch1->active[subframe] == 1) { +#else } else if (dlsch1->active == 1) { +#endif switch (rel8->precoding_information) { case 0: // one layer per transport block dlsch0_harq->mimo_mode = ALAMOUTI; @@ -1712,10 +1756,18 @@ LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n" } // reset HARQ process if this is the first transmission +#ifdef UE_EXPANSION + if ((dlsch0->active[subframe]==1) && (dlsch0_harq->round == 0)) +#else if ((dlsch0->active==1) && (dlsch0_harq->round == 0)) +#endif dlsch0_harq->status = ACTIVE; +#ifdef UE_EXPANSION + if ((dlsch1->active[subframe]==1) && (dlsch1_harq->round == 0)) +#else if ((dlsch1->active==1) && (dlsch1_harq->round == 0)) +#endif dlsch1_harq->status = ACTIVE; dlsch0->rnti = rel8->rnti; @@ -1881,8 +1933,13 @@ LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n" printf("RV0 = %d, RV1 = %d. MCS0 = %d, MCS1=%d\n", rel8->redundancy_version_1, rel8->redundancy_version_2, rel8->mcs_1, rel8->mcs_2); #endif if (TB0_active && TB1_active && rel8->transport_block_to_codeword_swap_flag==0) { +#ifdef UE_EXPANSION + dlsch0->active[subframe] = 1; + dlsch1->active[subframe] = 1; +#else dlsch0->active = 1; dlsch1->active = 1; +#endif dlsch0->harq_mask |= (1<harq_process); dlsch1->harq_mask |= (1<harq_process); dlsch0_harq = dlsch0->harq_processes[rel8->harq_process]; @@ -1904,8 +1961,13 @@ LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n" else if (TB0_active && TB1_active && rel8->transport_block_to_codeword_swap_flag==1) { dlsch0 = eNB->dlsch[UE_id][1]; dlsch1 = eNB->dlsch[UE_id][0]; +#ifdef UE_EXPANSION + dlsch0->active[subframe] = 1; + dlsch1->active[subframe] = 1; +#else dlsch0->active = 1; dlsch1->active = 1; +#endif dlsch0->harq_mask |= (1<harq_process); dlsch1->harq_mask |= (1<harq_process); @@ -1923,7 +1985,11 @@ LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n" dlsch1_harq->codeword=0; } else if (TB0_active && (TB1_active==0)) { +#ifdef UE_EXPANSION + dlsch0->active[subframe] = 1; +#else dlsch0->active = 1; +#endif dlsch0->harq_mask |= (1<harq_process); dlsch0_harq = dlsch0->harq_processes[rel8->harq_process]; dlsch0_harq->mcs = rel8->mcs_1; @@ -1938,7 +2004,11 @@ LOG_D(PHY,"NFAPI: harq_pid %d harq_mask %x, round %d ndi (%d,%d) rnti type %d\n" #endif } else if ((TB0_active==0) && TB1_active) { +#ifdef UE_EXPANSION + dlsch1->active[subframe] = 1; +#else dlsch1->active = 1; +#endif dlsch1->harq_mask |= (1<harq_process); dlsch1_harq = dlsch1->harq_processes[rel8->harq_process]; dlsch1_harq->mcs = rel8->mcs_2; @@ -2201,7 +2271,11 @@ void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,mDCI_ALLOC_t *d case 10: // Format 6-1A dci_alloc->format = format6_1A; +#ifdef UE_EXPANSION + dlsch0->active[subframe] = 1; +#else dlsch0->active = 1; +#endif switch (fp->N_RB_DL) { case 25: @@ -2254,7 +2328,11 @@ void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,mDCI_ALLOC_t *d break; case 11: // Format 6-1B dci_alloc->format = format6_1B; +#ifdef UE_EXPANSION + dlsch0->active[subframe] = 1; +#else dlsch0->active = 1; +#endif switch (fp->N_RB_DL) { case 25: @@ -2294,7 +2372,11 @@ void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,mDCI_ALLOC_t *d } case 12: // Format 6-2 dci_alloc->format = format6_2; +#ifdef UE_EXPANSION + dlsch0->active[subframe] = 1; +#else dlsch0->active = 1; +#endif switch (fp->N_RB_DL) { case 25: dci_alloc->dci_length = sizeof_DCI6_2_5MHz_t; @@ -2371,8 +2453,12 @@ void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,mDCI_ALLOC_t *d //LOG_E(PHY,"Invalid beamforming mode %dL\n", beamforming_mode); dlsch0_harq->dl_power_off = 1; - + +#ifdef UE_EXPANSION + dlsch0->active[subframe] = 1; +#else dlsch0->active = 1; +#endif dlsch0->harq_mask |= (1<harq_process); diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h index f1f4be3072..b293e56b87 100644 --- a/openair1/PHY/LTE_TRANSPORT/defs.h +++ b/openair1/PHY/LTE_TRANSPORT/defs.h @@ -102,6 +102,12 @@ typedef enum { DISABLED } SCH_status_t; +#ifdef Rel14 +typedef enum { + CEmodeA = 0, + CEmodeB = 1 +} CEmode_t; +#endif typedef struct { /// Status Flag indicating for this DLSCH (idle,active,disabled) @@ -178,6 +184,15 @@ typedef struct { uint8_t first_layer; /// codeword this transport block is mapped to uint8_t codeword; +#ifdef UE_EXPANSION +#ifdef Rel14 + /// indicator that this DLSCH corresponds to SIB1-BR, needed for c_init for scrambling + uint8_t sib1_br_flag; + /// initial absolute subframe (see 36.211 Section 6.3.1), needed for c_init for scrambling + uint16_t i0; + CEmode_t CEmode; +#endif +#endif } LTE_DL_eNB_HARQ_t; typedef struct { @@ -254,13 +269,6 @@ typedef struct { uint8_t decode_phich; } LTE_UL_UE_HARQ_t; -#ifdef Rel14 -typedef enum { - CEmodeA = 0, - CEmodeB = 1 -} CEmode_t; -#endif - typedef struct { /// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding) int32_t *txdataF[8]; @@ -271,7 +279,11 @@ typedef struct { /// Allocated RNTI (0 means DLSCH_t is not currently used) uint16_t rnti; /// Active flag for baseband transmitter processing +#ifdef UE_EXPANSION + uint8_t active[10]; +#else uint8_t active; +#endif /// HARQ process mask, indicates which processes are currently active uint16_t harq_mask; /// Indicator of TX activation per subframe. Used during PUCCH detection for ACK/NAK. @@ -302,6 +314,7 @@ typedef struct { int16_t sqrt_rho_a; /// amplitude of PDSCH (compared to RS) in symbols containing pilots int16_t sqrt_rho_b; +#ifndef UE_EXPANSION #ifdef Rel14 /// indicator that this DLSCH corresponds to SIB1-BR, needed for c_init for scrambling uint8_t sib1_br_flag; @@ -309,6 +322,7 @@ typedef struct { uint16_t i0; CEmode_t CEmode; #endif +#endif } LTE_eNB_DLSCH_t; #define PUSCH_x 2 diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index dbfae80840..7482524d41 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -246,7 +246,12 @@ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch) if (dlsch) { Mdlharq = dlsch->Mdlharq; dlsch->rnti = 0; +#ifdef UE_EXPANSION + for (i=0; i<10; i++) + dlsch->active[i] = 0; +#else dlsch->active = 0; +#endif for (i=0; i<10; i++) dlsch->harq_ids[i] = Mdlharq; diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c index d90f4c66d2..83392b18a9 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c @@ -92,13 +92,27 @@ void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms, uint8_t Nacc=4; uint16_t j0,j,idelta; uint16_t i = (Ns>>1) + (10*frame); +#ifdef UE_EXPANSION + uint16_t i0 = dlsch->harq_processes[harq_pid]->i0; +#else uint16_t i0 = dlsch->i0; +#endif +#ifdef UE_EXPANSION + if (dlsch->harq_processes[harq_pid]->sib1_br_flag==1) Nacc=1; +#else if (dlsch->sib1_br_flag==1) Nacc=1; +#endif else if (dlsch->rnti == 0xFFFF || dlsch->rnti == 0xFFFE) Nacc = (frame_parms->frame_type == TDD) ? 10 : 4; +#ifdef UE_EXPANSION + // Note: above SC-RNTI will also have to be added when/if implemented + else if (dlsch->harq_processes[harq_pid]->CEmode == CEmodeA) Nacc=1; + else if (dlsch->harq_processes[harq_pid]->CEmode == CEmodeB) Nacc = (frame_parms->frame_type == TDD) ? 10 : 4; +#else // Note: above SC-RNTI will also have to be added when/if implemented else if (dlsch->CEmode == CEmodeA) Nacc=1; else if (dlsch->CEmode == CEmodeB) Nacc = (frame_parms->frame_type == TDD) ? 10 : 4; +#endif if (frame_parms->frame_type == FDD || Nacc == 1) idelta = 0; else idelta = Nacc-2; @@ -111,7 +125,11 @@ void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms, // x1 is set in lte_gold_generic if (mbsfn_flag == 0) { #ifdef Rel14 +#ifdef UE_EXPANSION + if (dlsch->harq_processes[harq_pid]->i0 != 0xFFFF) { +#else if (dlsch->i0 != 0xFFFF) { +#endif // rule for BL/CE UEs from Section 6.3.1 in 36.211 x2= (dlsch->rnti<<14) + (q<<13) + ((((j0+j)*Nacc)%10)<<9) + frame_parms->Nid_cell; if ((frame&1023) < 200) LOG_D(PHY,"Scrambling init for (i0 %d, i %d, j0 %d, j %d, Nacc %d) => x2 %d\n",i0,i,j0,j,Nacc,x2); diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index c1d3ba7ce6..6f91b61375 100644 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -422,6 +422,34 @@ typedef struct RU_proc_t_s { int num_slaves; /// array of pointers to slaves struct RU_proc_t_s **slave_proc; +#ifdef UE_EXPANSION + /// pthread structure for PRACH thread + pthread_t pthread_phy_tx; + pthread_mutex_t mutex_phy_tx; + pthread_cond_t cond_phy_tx; + /// \internal This variable is protected by \ref mutex_phy_tx. + int instance_cnt_phy_tx; + /// frame to act upon for transmission + int frame_phy_tx; + /// subframe to act upon for transmission + int subframe_phy_tx; + /// timestamp to send to "slave rru" + openair0_timestamp timestamp_phy_tx; + /// pthread structure for RF TX thread + pthread_t pthread_rf_tx; + pthread_mutex_t mutex_rf_tx; + pthread_cond_t cond_rf_tx; + /// \internal This variable is protected by \ref mutex_rf_tx. + int instance_cnt_rf_tx; +#endif +#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2) + pthread_t pthread_pre_scd; + /// condition variable for time processing thread + pthread_cond_t cond_pre_scd; + /// mutex for time thread + pthread_mutex_t mutex_pre_scd; + int instance_pre_scd; +#endif } RU_proc_t; /// Context data structure for eNB subframe processing @@ -556,14 +584,6 @@ typedef struct eNB_proc_t_s { te_params tep; /// set of scheduling variables RXn-TXnp4 threads eNB_rxtx_proc_t proc_rxtx[2]; -#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2) - pthread_t pthread_pre_scd; - /// condition variable for time processing thread - pthread_cond_t cond_pre_scd; - /// mutex for time thread - pthread_mutex_t mutex_pre_scd; - int instance_pre_scd; -#endif } eNB_proc_t; diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c index c93934b011..dbce91776d 100644 --- a/openair1/SCHED/fapi_l1.c +++ b/openair1/SCHED/fapi_l1.c @@ -156,11 +156,19 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, // compute DL power control parameters eNB->pdsch_config_dedicated[UE_id].p_a = rel8->pa; +#ifdef UE_EXPANSION + if (dlsch0->active[proc->subframe_tx]){ +# else if (dlsch0->active){ +#endif computeRhoA_eNB(&eNB->pdsch_config_dedicated[UE_id], dlsch0,dlsch0_harq->dl_power_off, eNB->frame_parms.nb_antenna_ports_eNB); computeRhoB_eNB(&eNB->pdsch_config_dedicated[UE_id],&(eNB->frame_parms.pdsch_config_common),eNB->frame_parms.nb_antenna_ports_eNB,dlsch0,dlsch0_harq->dl_power_off); } +#ifdef UE_EXPANSION + if (dlsch1->active[proc->subframe_tx]){ +#else if (dlsch1->active){ +#endif computeRhoA_eNB(&eNB->pdsch_config_dedicated[UE_id], dlsch1,dlsch1_harq->dl_power_off, eNB->frame_parms.nb_antenna_ports_eNB); computeRhoB_eNB(&eNB->pdsch_config_dedicated[UE_id],&(eNB->frame_parms.pdsch_config_common),eNB->frame_parms.nb_antenna_ports_eNB,dlsch1,dlsch1_harq->dl_power_off); } @@ -183,17 +191,29 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, } #ifdef Rel14 +#ifdef UE_EXPANSION + dlsch0_harq->sib1_br_flag=0; +#else dlsch0->sib1_br_flag=0; +#endif if ((rel13->pdsch_payload_type <2) && (rel13->ue_type>0)) { // this is a BR/CE UE and SIB1-BR/SI-BR dlsch0->rnti = 0xFFFF; dlsch0->Kmimo = 1; dlsch0->Mdlharq = 4; dlsch0->Nsoft = 25344; +#ifdef UE_EXPANSION + dlsch0_harq->i0 = rel13->initial_transmission_sf_io; +#else dlsch0->i0 = rel13->initial_transmission_sf_io; +#endif dlsch0_harq->pdsch_start = rel10->pdsch_start; +#ifdef UE_EXPANSION + if (rel13->pdsch_payload_type == 0) dlsch0_harq->sib1_br_flag=1; +#else if (rel13->pdsch_payload_type == 0) dlsch0->sib1_br_flag=1; +#endif // configure PDSCH switch (eNB->frame_parms.N_RB_DL) { @@ -220,7 +240,11 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, dlsch0_harq->rb_alloc[3] = localRIV2alloc_LUT100_3[rel8->resource_block_coding]; } +#ifdef UE_EXPANSION + dlsch0->active[proc->subframe_tx]= 1; +#else dlsch0->active = 1; +#endif dlsch0_harq->nb_rb = 6; dlsch0_harq->vrb_type = LOCALIZED; @@ -235,7 +259,11 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, dlsch0_harq->codeword = 0; } else { +#ifdef UE_EXPANSION + dlsch0_harq->i0 = 0xFFFF; +#else dlsch0->i0 = 0xFFFF; +#endif } #endif } diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 3debfee997..8500cd8b9b 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -376,8 +376,11 @@ void pdsch_procedures(PHY_VARS_eNB *eNB, dlsch1); stop_meas(&eNB->dlsch_modulation_stats); - +#ifdef UE_EXPANSION + dlsch->active[subframe] = 0; +#else dlsch->active = 0; +#endif dlsch_harq->round++; } @@ -512,7 +515,11 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, if ((dlsch0)&& (dlsch0->rnti>0)&& +#ifdef UE_EXPANSION + (dlsch0->active[subframe] == 1)) { +#else (dlsch0->active == 1)) { +#endif // get harq_pid harq_pid = dlsch0->harq_ids[subframe]; @@ -532,7 +539,11 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, else if ((dlsch0)&& (dlsch0->rnti>0)&& - (dlsch0->active == 0)) { +#ifdef UE_EXPANSION + (dlsch0->active[subframe] == 0)) { +#else + (dlsch0->active == 0)) { +#endif // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later) dlsch0->subframe_tx[subframe]=0; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 1b3a85e5ee..7ed20d55ae 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -409,6 +409,10 @@ set_ul_DAI(int module_idP, int UE_idP, int CC_idP, int frameP, } +#ifdef UE_EXPANSION +extern volatile int16_t phy_tx_txdataF_end; +extern int oai_exit; +#endif // changes to pre-processor for eMTC //------------------------------------------------------------------------------ @@ -546,6 +550,12 @@ schedule_ue_spec(module_id_t module_idP, stop_meas(&eNB->schedule_dlsch_preprocessor); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_OUT); + +#ifdef UE_EXPANSION + struct timespec time_req, time_rem; + time_req.tv_sec = 0; + time_req.tv_nsec = 10000; +#endif for (CC_id=0; CC_idDLSCH_pdu[CC_id][0][UE_id].payload[0], num_sdus, //num_sdus sdu_lengths, // diff --git a/openair2/LAYER2/MAC/extern.h b/openair2/LAYER2/MAC/extern.h index 9f29af5b9b..790f89d2c7 100644 --- a/openair2/LAYER2/MAC/extern.h +++ b/openair2/LAYER2/MAC/extern.h @@ -113,10 +113,6 @@ extern uint8_t dlsch_ue_select_tbl_in_use; extern uint8_t new_dlsch_ue_select_tbl_in_use; extern boolean_t pre_scd_activeUE[NUMBER_OF_UE_MAX]; extern eNB_UE_STATS pre_scd_eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; -/// sorted downlink component carrier for the scheduler -extern int pre_scd_ordered_CCids[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; -/// number of downlink active component carrier -extern int pre_scd_numactiveCCs[NUMBER_OF_UE_MAX]; #endif #endif //DEF_H diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index bedd37165c..ffe24cae25 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -548,20 +548,33 @@ void sort_UEs(module_id_t Mod_idP, int frameP, sub_frame_t subframeP) } #if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2) +inline uint16_t search_rbs_required(uint16_t mcs, uint16_t TBS,uint16_t NB_RB, uint16_t step_size){ + uint16_t nb_rb,i_TBS,tmp_TBS; + i_TBS=get_I_TBS(mcs); + for(nb_rb=step_size;nb_rb>3; + if(TBScommon_channels[CC_id].mib->message.dl_Bandwidth); + if(N_RB_DL==50) step_size=3; + if(N_RB_DL==100) step_size=4; memset(nb_rbs_required, 0, sizeof(uint16_t)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); + UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; for (UE_id = 0; UE_id 0) - LOG_D(MAC, - "[eNB %d] Frame %d Subframe %d : RLC status for UE %d %x in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n", - module_idP, frameP, subframeP, UE_id, rnti, - lc_id, UE_template.dl_pdus_in_buffer[lc_id], - UE_template.dl_buffer_info[lc_id], - UE_template.dl_buffer_head_sdu_creation_time[lc_id], - UE_template. - dl_buffer_head_sdu_remaining_size_to_send[lc_id], - UE_template.dl_buffer_head_sdu_is_segmented[lc_id]); -#endif + UE_template.dl_buffer_total += rlc_status.bytes_in_buffer; //storing the total dlsch buffer } - - if (UE_template.dl_buffer_total > 0) - LOG_D(MAC, - "[eNB %d] Frame %d Subframe %d : RLC status for UE %d %x: total DL buffer size %d and total number of pdu %d \n", - module_idP, frameP, subframeP, UE_id,rnti, - UE_template.dl_buffer_total, - UE_template.dl_pdus_total); // end of store dlsch buffer // assgin rbs required // Calculate the number of RBs required by each UE on the basis of logical channel's buffer //update CQI information across component carriers - for (i = 0; i < pre_scd_numactiveCCs[UE_id]; i++) { - CC_id = pre_scd_ordered_CCids[i][UE_id]; - eNB_UE_stats = &pre_scd_eNB_UE_stats[CC_id][UE_id]; + eNB_UE_stats = &pre_scd_eNB_UE_stats[CC_id][UE_id]; - eNB_UE_stats->dlsch_mcs1 = 28; - } + eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; - // provide the list of CCs sorted according to MCS - for (i = 0; i < pre_scd_numactiveCCs[UE_id]; i++) { - eNB_UE_stats_i = - &pre_scd_eNB_UE_stats[pre_scd_ordered_CCids[i][UE_id]][UE_id]; - for (j = i + 1; j < pre_scd_numactiveCCs[UE_id]; j++) { - DevAssert(j < MAX_NUM_CCs); - eNB_UE_stats_j = - &pre_scd_eNB_UE_stats[pre_scd_ordered_CCids[j][UE_id]][UE_id]; - if (eNB_UE_stats_j->dlsch_mcs1 - > eNB_UE_stats_i->dlsch_mcs1) { - tmp = pre_scd_ordered_CCids[i][UE_id]; - pre_scd_ordered_CCids[i][UE_id] = - pre_scd_ordered_CCids[j][UE_id]; - pre_scd_ordered_CCids[j][UE_id] = tmp; - } - } - } if (UE_template.dl_buffer_total > 0) { - LOG_D(MAC, "[preprocessor] assign RB for UE %d\n", UE_id); - - for (i = 0; i < pre_scd_numactiveCCs[UE_id]; i++) { - CC_id = pre_scd_ordered_CCids[i][UE_id]; - eNB_UE_stats = &pre_scd_eNB_UE_stats[CC_id][UE_id]; - - if (eNB_UE_stats->dlsch_mcs1 == 0) { - nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small - } else { - nb_rbs_required[CC_id][UE_id] = - min_rb_unit[CC_id]; - } - - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_rbs_required[CC_id][UE_id]); - - LOG_D(MAC, - "[preprocessor] start RB assignement for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n", - UE_id, CC_id, - UE_template.dl_buffer_total, - nb_rbs_required[CC_id][UE_id], - eNB_UE_stats->dlsch_mcs1, TBS); - - N_RB_DL = - to_prb( - RC.mac[module_idP]->common_channels[CC_id].mib->message.dl_Bandwidth); - - /* calculating required number of RBs for each UE */ - while (TBS - < UE_template.dl_buffer_total) { - nb_rbs_required[CC_id][UE_id] += - min_rb_unit[CC_id]; - if (nb_rbs_required[CC_id][UE_id] > N_RB_DL) { - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, N_RB_DL); - nb_rbs_required[CC_id][UE_id] = N_RB_DL; - break; - } - - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_rbs_required[CC_id][UE_id]); - } // end of while - LOG_D(MAC, - "[eNB %d] Frame %d Subframe %d: UE %d on CC %d: RB unit %d, nb_required RB %d (TBS %d, mcs %d)\n", - module_idP, frameP, subframeP, UE_id, CC_id, - min_rb_unit[CC_id], - nb_rbs_required[CC_id][UE_id], TBS, - eNB_UE_stats->dlsch_mcs1); - } + nb_rbs_required[CC_id][UE_id] = search_rbs_required(eNB_UE_stats->dlsch_mcs1, UE_template.dl_buffer_total, N_RB_DL, step_size); } } } diff --git a/openair2/LAYER2/MAC/vars.h b/openair2/LAYER2/MAC/vars.h index b6db7fe79e..01ece20d48 100644 --- a/openair2/LAYER2/MAC/vars.h +++ b/openair2/LAYER2/MAC/vars.h @@ -157,10 +157,6 @@ uint8_t dlsch_ue_select_tbl_in_use; uint8_t new_dlsch_ue_select_tbl_in_use; boolean_t pre_scd_activeUE[NUMBER_OF_UE_MAX]; eNB_UE_STATS pre_scd_eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; -/// sorted downlink component carrier for the scheduler -int pre_scd_ordered_CCids[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; -/// number of downlink active component carrier -int pre_scd_numactiveCCs[NUMBER_OF_UE_MAX]; #endif #endif diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 9b46ae7f32..39d059d3a3 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -95,10 +95,6 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "T.h" -#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2) -#include "pdcp.h" -#endif - //#define DEBUG_THREADS 1 //#define USRP_DEBUG 1 @@ -191,9 +187,9 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam if (oai_exit) return(-1); - +#if (!defined(UE_EXPANSION_SIM2)) &&(!defined(UE_EXPANSION)) phy_procedures_eNB_TX(eNB, proc, no_relay, NULL, 1); - +#endif if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) return(-1); stop_meas( &softmodem_stats_rxtx_sf ); @@ -500,61 +496,7 @@ void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { } #endif -#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2) -void* pre_scd_thread( void* param ){ - static int eNB_pre_scd_status; - protocol_ctxt_t ctxt; - int frame; - int subframe; - int min_rb_unit[MAX_NUM_CCs]; - int CC_id; - int Mod_id; - PHY_VARS_eNB *eNB= (PHY_VARS_eNB *)param; - eNB_proc_t *proc = &eNB->proc; - Mod_id = eNB->Mod_id; - frame = 0; - subframe = 4; - thread_top_init("pre_scd_thread",0,870000,1000000,1000000); - - while (!oai_exit) { - if(oai_exit){ - break; - } - pthread_mutex_lock(&proc->mutex_pre_scd ); - if (proc->instance_pre_scd < 0) { - pthread_cond_wait(&proc->cond_pre_scd, &proc->mutex_pre_scd); - } - pthread_mutex_unlock(&proc->mutex_pre_scd); - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, Mod_id, ENB_FLAG_YES, - NOT_A_RNTI, frame, subframe, - eNB->Mod_id); - pdcp_run(&ctxt); - - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - - rrc_rx_tx(&ctxt, 0, // eNB index, unused in eNB - CC_id); - min_rb_unit[CC_id] = get_min_rb_unit(Mod_id, CC_id); - } - - pre_scd_nb_rbs_required(Mod_id, frame, subframe,min_rb_unit,pre_nb_rbs_required[new_dlsch_ue_select_tbl_in_use]); - - if (subframe==9) { - subframe=0; - frame++; - frame&=1023; - } else { - subframe++; - } - pthread_mutex_lock(&proc->mutex_pre_scd ); - proc->instance_pre_scd--; - pthread_mutex_unlock(&proc->mutex_pre_scd); - } - eNB_pre_scd_status = 0; - return &eNB_pre_scd_status; -} -#endif /*! * \brief The prach receive thread of eNB. @@ -712,14 +654,6 @@ void init_eNB_proc(int inst) { // attr_te = &proc->attr_te; #endif -#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2) - proc->instance_pre_scd = -1; - pthread_mutex_init( &proc->mutex_pre_scd, NULL); - pthread_cond_init( &proc->cond_pre_scd, NULL); - pthread_create(&proc->pthread_pre_scd, NULL, pre_scd_thread, eNB); - pthread_setname_np(proc->pthread_pre_scd, "pre_scd_thread"); -#endif - if (eNB->single_thread_flag==0) { pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, &proc_rxtx[0] ); pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] ); @@ -806,13 +740,6 @@ void kill_eNB_proc(int inst) { pthread_mutex_destroy( &proc->mutex_prach_br ); pthread_cond_destroy( &proc->cond_prach_br ); #endif -#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2) - proc->instance_pre_scd = 0; - pthread_cond_signal( &proc->cond_pre_scd ); - pthread_join( proc->pthread_pre_scd, (void**)&status ); - pthread_mutex_destroy( &proc->mutex_pre_scd ); - pthread_cond_destroy( &proc->cond_pre_scd ); -#endif LOG_I(PHY, "Destroying UL_INFO mutex\n"); pthread_mutex_destroy(&eNB->UL_INFO_mutex); int i; diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index 430f1e6426..18d9cd42fc 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -110,6 +110,10 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "T.h" +#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2) +#include "pdcp.h" +#endif + extern volatile int oai_exit; @@ -730,10 +734,16 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; // synchronize first reception to frame 0 subframe 0 +#ifdef UE_EXPANSION + proc->timestamp_phy_tx = proc->timestamp_rx+(3*fp->samples_per_tti); + proc->subframe_phy_tx = (proc->subframe_rx+3)%10; + proc->frame_phy_tx = (proc->subframe_rx>6) ? (proc->frame_rx+1)&1023 : proc->frame_rx; +#else proc->timestamp_tx = proc->timestamp_rx+(4*fp->samples_per_tti); proc->subframe_tx = (proc->subframe_rx+4)%10; proc->frame_tx = (proc->subframe_rx>5) ? (proc->frame_rx+1)&1023 : proc->frame_rx; - +#endif + LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, subframe %d\n", ru->idx, 0, @@ -1383,6 +1393,11 @@ static void* ru_stats_thread(void* param) { return(NULL); } +#ifdef UE_EXPANSION +int first_phy_tx = 1; +volatile int16_t phy_tx_txdataF_end; +volatile int16_t phy_tx_end; +#endif static void* ru_thread( void* param ) { static int ru_thread_status; @@ -1400,6 +1415,11 @@ static void* ru_thread( void* param ) { dlsch_ue_select_tbl_in_use = 1; #endif +#ifdef UE_EXPANSION + struct timespec time_req, time_rem; + time_req.tv_sec = 0; + time_req.tv_nsec = 10000; +#endif // set default return value thread_top_init("ru_thread",0,870000,1000000,1000000); @@ -1489,6 +1509,30 @@ static void* ru_thread( void* param ) { ru->do_prach, is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx), proc->frame_rx,proc->subframe_rx); + +#ifdef UE_EXPANSION + if(first_phy_tx == 0) + { + phy_tx_end = 0; + phy_tx_txdataF_end = 0; + if(pthread_mutex_lock(&ru->proc.mutex_phy_tx) != 0){ + LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for phy tx thread (IC %d)\n", ru->proc.instance_cnt_phy_tx); + exit_fun( "error locking mutex_rxtx" ); + } + if (ru->proc.instance_cnt_phy_tx==-1) { + ++ru->proc.instance_cnt_phy_tx; + + // the thread can now be woken up + AssertFatal(pthread_cond_signal(&ru->proc.cond_phy_tx) == 0, "ERROR pthread_cond_signal for phy_tx thread\n"); + } + else LOG_W(PHY,"phy tx thread busy, skipping\n"); + pthread_mutex_unlock( &ru->proc.mutex_phy_tx ); + } else { + phy_tx_end = 1; + phy_tx_txdataF_end = 1; + } + first_phy_tx = 0; +#endif if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)==1)) wakeup_prach_ru(ru); #ifdef Rel14 @@ -1511,27 +1555,25 @@ static void* ru_thread( void* param ) { dlsch_ue_select_tbl_in_use = !dlsch_ue_select_tbl_in_use; memcpy(&pre_scd_eNB_UE_stats,&RC.mac[ru->eNB_list[0]->Mod_id]->UE_list.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); memcpy(&pre_scd_activeUE, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_list.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX); - memcpy(&pre_scd_ordered_CCids, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_list.ordered_CCids, sizeof(int)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); - memcpy(&pre_scd_numactiveCCs, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_list.numactiveCCs, sizeof(int)*NUMBER_OF_UE_MAX); - if (pthread_mutex_lock(&ru->eNB_list[0]->proc.mutex_pre_scd)!= 0) { - LOG_E( MAC, "[eNB] error locking MAC proc mutex for eNB pre scd\n"); + if (pthread_mutex_lock(&ru->proc.mutex_pre_scd)!= 0) { + LOG_E( PHY, "[eNB] error locking proc mutex for eNB pre scd\n"); exit_fun("error locking mutex_time"); } - ru->eNB_list[0]->proc.instance_pre_scd++; + ru->proc.instance_pre_scd++; - if (ru->eNB_list[0]->proc.instance_pre_scd == 0) { - if (pthread_cond_signal(&ru->eNB_list[0]->proc.cond_pre_scd) != 0) { - LOG_E( MAC, "[eNB] ERROR pthread_cond_signal for eNB time sync\n" ); + if (ru->proc.instance_pre_scd == 0) { + if (pthread_cond_signal(&ru->proc.cond_pre_scd) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB pre scd\n" ); exit_fun( "ERROR pthread_cond_signal cond_pre_scd" ); } }else{ - LOG_E( MAC, "[eNB] frame %d subframe %d rxtx busy instance_pre_scd %d\n", - frame,subframe,ru->eNB_list[0]->proc.instance_pre_scd ); + LOG_E( PHY, "[eNB] frame %d subframe %d rxtx busy instance_pre_scd %d\n", + frame,subframe,ru->proc.instance_pre_scd ); } - if (pthread_mutex_unlock(&ru->eNB_list[0]->proc.mutex_pre_scd)!= 0) { - LOG_E( MAC, "[eNB] error unlocking mutex_pre_scd mutex for eNB pre scd\n"); + if (pthread_mutex_unlock(&ru->proc.mutex_pre_scd)!= 0) { + LOG_E( PHY, "[eNB] error unlocking mutex_pre_scd mutex for eNB pre scd\n"); exit_fun("error unlocking mutex_pre_scd"); } #endif @@ -1543,6 +1585,7 @@ static void* ru_thread( void* param ) { wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread"); +#ifndef UE_EXPANSION // do TX front-end processing if needed (precoding and/or IDFTs) if (ru->feptx_prec) ru->feptx_prec(ru); @@ -1552,6 +1595,12 @@ 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_out) ru->fh_north_out(ru); +#else + while((!oai_exit)&&(phy_tx_end == 0)){ + nanosleep(&time_req,&time_rem); + continue; + } +#endif } @@ -1643,6 +1692,161 @@ void *ru_thread_synch(void *arg) { } +#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2) +void* pre_scd_thread( void* param ){ + static int eNB_pre_scd_status; + protocol_ctxt_t ctxt; + int frame; + int subframe; + int min_rb_unit[MAX_NUM_CCs]; + int CC_id; + int Mod_id; + RU_t *ru = (RU_t*)param; + Mod_id = ru->eNB_list[0]->Mod_id; + + frame = 0; + subframe = 4; + thread_top_init("pre_scd_thread",0,870000,1000000,1000000); + + while (!oai_exit) { + if(oai_exit){ + break; + } + pthread_mutex_lock(&ru->proc.mutex_pre_scd ); + if (ru->proc.instance_pre_scd < 0) { + pthread_cond_wait(&ru->proc.cond_pre_scd, &ru->proc.mutex_pre_scd); + } + pthread_mutex_unlock(&ru->proc.mutex_pre_scd); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, Mod_id, ENB_FLAG_YES, + NOT_A_RNTI, frame, subframe,Mod_id); + pdcp_run(&ctxt); + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + + rrc_rx_tx(&ctxt, 0, // eNB index, unused in eNB + CC_id); + min_rb_unit[CC_id] = get_min_rb_unit(Mod_id, CC_id); + } + + pre_scd_nb_rbs_required(Mod_id, frame, subframe,min_rb_unit,pre_nb_rbs_required[new_dlsch_ue_select_tbl_in_use]); + + if (subframe==9) { + subframe=0; + frame++; + frame&=1023; + } else { + subframe++; + } + pthread_mutex_lock(&ru->proc.mutex_pre_scd ); + ru->proc.instance_pre_scd--; + pthread_mutex_unlock(&ru->proc.mutex_pre_scd); + } + eNB_pre_scd_status = 0; + return &eNB_pre_scd_status; +} +#endif + +#ifdef UE_EXPANSION +/*! + * \brief The phy tx thread of eNB. + * \param param is a \ref eNB_proc_t structure which contains the info what to process. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ +static void* eNB_thread_phy_tx( void* param ) { + static int eNB_thread_phy_tx_status; + + + RU_t *ru = (RU_t*)param; + RU_proc_t *proc = &ru->proc; + PHY_VARS_eNB **eNB_list = ru->eNB_list; + + eNB_rxtx_proc_t proc_rxtx; + + // set default return value + eNB_thread_phy_tx_status = 0; + + thread_top_init("eNB_thread_phy_tx",1,500000L,1000000L,20000000L); + + + while (!oai_exit) { + + if (oai_exit) break; + + + if (wait_on_condition(&proc->mutex_phy_tx,&proc->cond_phy_tx,&proc->instance_cnt_phy_tx,"eNB_phy_tx_thread") < 0) break; + + LOG_D(PHY,"Running eNB phy tx procedures\n"); + if(ru->num_eNB == 1){ + proc_rxtx.subframe_tx = proc->subframe_phy_tx; + proc_rxtx.frame_tx = proc->frame_phy_tx; + phy_procedures_eNB_TX(eNB_list[0], &proc_rxtx, no_relay, NULL, 1); + ru->proc.frame_tx = proc->frame_phy_tx; + ru->proc.subframe_tx = proc->subframe_phy_tx; + ru->proc.timestamp_tx = proc->timestamp_phy_tx; + phy_tx_txdataF_end = 1; + if(pthread_mutex_lock(&ru->proc.mutex_rf_tx) != 0){ + LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for rf tx thread (IC %d)\n", ru->proc.instance_cnt_rf_tx); + exit_fun( "error locking mutex_rf_tx" ); + } + if (ru->proc.instance_cnt_rf_tx==-1) { + ++ru->proc.instance_cnt_rf_tx; + + // the thread can now be woken up + AssertFatal(pthread_cond_signal(&ru->proc.cond_rf_tx) == 0, "ERROR pthread_cond_signal for rf_tx thread\n"); + } + else LOG_W(PHY,"rf tx thread busy, skipping\n"); + pthread_mutex_unlock( &ru->proc.mutex_rf_tx ); + } + if (release_thread(&proc->mutex_phy_tx,&proc->instance_cnt_phy_tx,"eNB_thread_phy_tx") < 0) break; + phy_tx_end = 1; + } + + LOG_I(PHY, "Exiting eNB thread PHY TX\n"); + + eNB_thread_phy_tx_status = 0; + return &eNB_thread_phy_tx_status; +} + + +static void* rf_tx( void* param ) { + static int rf_tx_status; + + RU_t *ru = (RU_t*)param; + RU_proc_t *proc = &ru->proc; + + // set default return value + rf_tx_status = 0; + + thread_top_init("rf_tx",1,500000L,1000000L,20000000L); + + while (!oai_exit) { + + if (oai_exit) break; + + + if (wait_on_condition(&proc->mutex_rf_tx,&proc->cond_rf_tx,&proc->instance_cnt_rf_tx,"rf_tx_thread") < 0) break; + + LOG_D(PHY,"Running eNB rf tx procedures\n"); + if(ru->num_eNB == 1){ + // do TX front-end processing if needed (precoding and/or IDFTs) + if (ru->feptx_prec) ru->feptx_prec(ru); + // do OFDM if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru); + // do outgoing fronthaul (south) if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru); + + if (ru->fh_north_out) ru->fh_north_out(ru); + } + if (release_thread(&proc->mutex_rf_tx,&proc->instance_cnt_rf_tx,"rf_tx") < 0) break; + } + + LOG_I(PHY, "Exiting rf TX\n"); + + rf_tx_status = 0; + return &rf_tx_status; +} +#endif + int start_if(struct RU_t_s *ru,struct PHY_VARS_eNB_s *eNB) { @@ -1713,6 +1917,15 @@ void init_RU_proc(RU_t *ru) { pthread_cond_init( &proc->cond_prach_br, NULL); pthread_attr_init( &proc->attr_prach_br); #endif + +#ifdef UE_EXPANSION + proc->instance_cnt_phy_tx = -1; + pthread_mutex_init( &proc->mutex_phy_tx, NULL); + pthread_cond_init( &proc->cond_phy_tx, NULL); + proc->instance_cnt_rf_tx = -1; + pthread_mutex_init( &proc->mutex_rf_tx, NULL); + pthread_cond_init( &proc->cond_rf_tx, NULL); +#endif #ifndef DEADLINE_SCHEDULER attr_FH = &proc->attr_FH; @@ -1725,6 +1938,19 @@ void init_RU_proc(RU_t *ru) { #endif pthread_create( &proc->pthread_FH, attr_FH, ru_thread, (void*)ru ); +#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2) + proc->instance_pre_scd = -1; + pthread_mutex_init( &proc->mutex_pre_scd, NULL); + pthread_cond_init( &proc->cond_pre_scd, NULL); + pthread_create(&proc->pthread_pre_scd, NULL, pre_scd_thread, (void*)ru); + pthread_setname_np(proc->pthread_pre_scd, "pre_scd_thread"); +#endif + +#ifdef UE_EXPANSION + pthread_create( &proc->pthread_phy_tx, NULL, eNB_thread_phy_tx, (void*)ru ); + pthread_setname_np( proc->pthread_phy_tx, "phy_tx_thread" ); + pthread_create( &proc->pthread_rf_tx, NULL, rf_tx, (void*)ru ); +#endif if (ru->function == NGFI_RRU_IF4p5) { pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void*)ru ); @@ -2141,8 +2367,32 @@ void init_RU(char *rf_config_file) { void stop_ru(RU_t *ru) { - +#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2) + int *status; +#endif printf("Stopping RU %p processing threads\n",(void*)ru); - +#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2) + if(ru){ + ru->proc.instance_pre_scd = 0; + pthread_cond_signal( &ru->proc.cond_pre_scd ); + pthread_join(ru->proc.pthread_pre_scd, (void**)&status ); + pthread_mutex_destroy(&ru->proc.mutex_pre_scd ); + pthread_cond_destroy(&ru->proc.cond_pre_scd ); + } +#endif +#ifdef UE_EXPANSION + if(ru){ + ru->proc.instance_cnt_phy_tx = 0; + pthread_cond_signal(&ru->proc.cond_phy_tx); + pthread_join( ru->proc.pthread_phy_tx, (void**)&status ); + pthread_mutex_destroy( &ru->proc.mutex_phy_tx ); + pthread_cond_destroy( &ru->proc.cond_phy_tx ); + ru->proc.instance_cnt_rf_tx = 0; + pthread_cond_signal(&ru->proc.cond_rf_tx); + pthread_join( ru->proc.pthread_rf_tx, (void**)&status ); + pthread_mutex_destroy( &ru->proc.mutex_rf_tx ); + pthread_cond_destroy( &ru->proc.cond_rf_tx ); + } +#endif } diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index e90fc4335c..e8b204a7b4 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1360,6 +1360,11 @@ int main( int argc, char **argv ) // cleanup if (UE_flag == 1) { } else { +#ifdef UE_EXPANSION + for (ru_id=0;ru_id Date: Fri, 26 Jan 2018 06:15:28 +0000 Subject: [PATCH 2/2] add remove ue info of pre_scd thread to freeList and for ru_thread to remove the UE in the freeList --- openair2/LAYER2/MAC/defs.h | 21 ++++++ openair2/RRC/LITE/proto.h | 7 ++ openair2/RRC/LITE/rrc_common.c | 4 ++ openair2/RRC/LITE/rrc_eNB.c | 113 +++++++++++++++++++++++++++++++++ targets/RT/USER/lte-enb.c | 4 ++ 5 files changed, 149 insertions(+) diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h index e55d403a22..85c02434a6 100644 --- a/openair2/LAYER2/MAC/defs.h +++ b/openair2/LAYER2/MAC/defs.h @@ -958,6 +958,24 @@ typedef struct { boolean_t active[NUMBER_OF_UE_MAX]; } UE_list_t; +#ifdef UE_EXPANSION +/*! \brief deleting control information*/ +typedef struct { + ///rnti of UE + rnti_t rnti; + ///remove UE context flag + boolean_t removeContextFlg; +} UE_free_ctrl; +/*! \brief REMOVE UE list used by eNB to order UEs/CC for deleting*/ +typedef struct { + /// deleting control info + UE_free_ctrl UE_free_ctrl[NUMBER_OF_UE_MAX+1]; + int num_UEs; + int head_freelist; ///the head position of the delete list + int tail_freelist; ///the tail position of the delete list +} UE_free_list_t; +#endif + /*! \brief eNB common channels */ typedef struct { int physCellId; @@ -1102,6 +1120,9 @@ typedef struct eNB_MAC_INST_s { time_stats_t schedule_mch; /// processing time of eNB ULSCH reception time_stats_t rx_ulsch_sdu; // include rlc_data_ind +#ifdef UE_EXPANSION + UE_free_list_t UE_free_list; +#endif } eNB_MAC_INST; /* diff --git a/openair2/RRC/LITE/proto.h b/openair2/RRC/LITE/proto.h index b3d5beb292..99362a02e7 100644 --- a/openair2/RRC/LITE/proto.h +++ b/openair2/RRC/LITE/proto.h @@ -470,4 +470,11 @@ void openair_rrc_top_init_ue( uint8_t HO_active ); +#ifdef UE_EXPANSION +pthread_mutex_t lock_ue_freelist; +void remove_UE_from_freelist(module_id_t mod_id, rnti_t rnti); +void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, boolean_t removeFlag); +void release_UE_in_freeList(module_id_t mod_id); +#endif + /** @}*/ diff --git a/openair2/RRC/LITE/rrc_common.c b/openair2/RRC/LITE/rrc_common.c index 47f67a1373..ad5b011c34 100644 --- a/openair2/RRC/LITE/rrc_common.c +++ b/openair2/RRC/LITE/rrc_common.c @@ -372,6 +372,7 @@ rrc_rx_tx( ue_context_p->ue_context.ue_release_timer_thres_rrc) { LOG_I(RRC,"Removing UE %x instance After UE_CONTEXT_RELEASE_Complete\n", ue_context_p->ue_context.rnti); ue_to_be_removed = ue_context_p; + ue_context_p->ue_context.ue_release_timer_rrc = 0; break; } } @@ -395,6 +396,9 @@ rrc_rx_tx( ue_context_p->ue_context.ue_release_timer_thres) { LOG_I(RRC,"Removing UE %x instance\n",ue_context_p->ue_context.rnti); ue_to_be_removed = ue_context_p; +#ifdef UE_EXPANSION + ue_context_p->ue_context.ue_release_timer = 0; +#endif break; } } diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c index ae7f823528..2678b6a0d8 100644 --- a/openair2/RRC/LITE/rrc_eNB.c +++ b/openair2/RRC/LITE/rrc_eNB.c @@ -780,11 +780,13 @@ rrc_eNB_free_UE(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_s* (void)ue_module_id; #endif rnti_t rnti = ue_context_pP->ue_context.rnti; +#ifndef UE_EXPANSION int i, j , CC_id, pdu_number; LTE_eNB_ULSCH_t *ulsch = NULL; nfapi_ul_config_request_body_t *ul_req_tmp = NULL; PHY_VARS_eNB *eNB_PHY = NULL; eNB_MAC_INST *eNB_MAC = RC.mac[enb_mod_idP]; +#endif AssertFatal(enb_mod_idP < NB_eNB_INST, "eNB inst invalid (%d/%d) for UE %x!", enb_mod_idP, NB_eNB_INST, rnti); /* ue_context_p = rrc_eNB_get_ue_context( @@ -813,6 +815,7 @@ rrc_eNB_free_UE(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_s* oai_emulation.info.eNB_ue_module_id_to_rnti[enb_mod_idP][ue_module_id] = NOT_A_RNTI; #endif #endif +#ifndef UE_EXPANSION for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { eNB_PHY = RC.eNB[enb_mod_idP][CC_id]; for (i=0; iUE_free_list; + free_list->UE_free_ctrl[free_list->head_freelist].rnti = 0; + free_list->head_freelist = (free_list->head_freelist + 1) % (NUMBER_OF_UE_MAX+1); + free_list->num_UEs--; + pthread_mutex_unlock(&lock_ue_freelist); +} + +void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, boolean_t removeFlag) +{ + UE_free_list_t *free_list = NULL; + eNB_MAC_INST *eNB_MAC = RC.mac[mod_id]; + pthread_mutex_lock(&lock_ue_freelist); + free_list = &eNB_MAC->UE_free_list; + free_list->UE_free_ctrl[free_list->tail_freelist].rnti = rnti; + free_list->UE_free_ctrl[free_list->tail_freelist].removeContextFlg = removeFlag; + free_list->num_UEs++; + free_list->tail_freelist = (free_list->tail_freelist + 1) % (NUMBER_OF_UE_MAX+1); + pthread_mutex_unlock(&lock_ue_freelist); +} + +void release_UE_in_freeList(module_id_t mod_id) +{ + int i, j , CC_id, pdu_number; + protocol_ctxt_t ctxt; + LTE_eNB_ULSCH_t *ulsch = NULL; + nfapi_ul_config_request_body_t *ul_req_tmp = NULL; + PHY_VARS_eNB *eNB_PHY = NULL; + struct rrc_eNB_ue_context_s *ue_context_pP = NULL; + eNB_MAC_INST *eNB_MAC = RC.mac[mod_id]; + boolean_t remove_UEContext; + rnti_t rnti; + int head, tail, ue_num; + + pthread_mutex_lock(&lock_ue_freelist); + head = eNB_MAC->UE_free_list.head_freelist; + tail = eNB_MAC->UE_free_list.tail_freelist; + if(head == tail){ + pthread_mutex_unlock(&lock_ue_freelist); + return; + } + if(tail < head){ + tail = head + eNB_MAC->UE_free_list.num_UEs; + } + pthread_mutex_unlock(&lock_ue_freelist); + + for(ue_num = head; ue_num < tail; ue_num++){ + ue_num = ue_num % (NUMBER_OF_UE_MAX+1); + rnti = eNB_MAC->UE_free_list.UE_free_ctrl[ue_num].rnti; + if(rnti != 0){ + remove_UEContext = eNB_MAC->UE_free_list.UE_free_ctrl[ue_num].removeContextFlg; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, mod_id, ENB_FLAG_YES, rnti, 0, 0,mod_id); + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + eNB_PHY = RC.eNB[mod_id][CC_id]; + for (i=0; i<=NUMBER_OF_UE_MAX; i++) { + ulsch = eNB_PHY->ulsch[i]; + if((ulsch != NULL) && (ulsch->rnti == rnti)){ + LOG_I(RRC, "clean_eNb_ulsch ulsch[%d] UE %x\n", i, rnti); + clean_eNb_ulsch(ulsch); + } + } + + for(j = 0; j < 10; j++){ + ul_req_tmp = &eNB_MAC->UL_req_tmp[CC_id][j].ul_config_request_body; + if(ul_req_tmp){ + pdu_number = ul_req_tmp->number_of_pdus; + for(int pdu_index = pdu_number-1; pdu_index >= 0; pdu_index--){ + if(ul_req_tmp->ul_config_pdu_list[pdu_index].ulsch_pdu.ulsch_pdu_rel8.rnti == rnti){ + LOG_I(RRC, "remove UE %x from ul_config_pdu_list %d/%d\n", rnti, pdu_index, pdu_number); + if(pdu_index < pdu_number -1){ + memcpy(&ul_req_tmp->ul_config_pdu_list[pdu_index], &ul_req_tmp->ul_config_pdu_list[pdu_index+1], (pdu_number-1-pdu_index) * sizeof(nfapi_ul_config_request_pdu_t)); + } + ul_req_tmp->number_of_pdus--; + } + } + } + } + } + rrc_mac_remove_ue(mod_id,rnti); + rrc_rlc_remove_ue(&ctxt); + pdcp_remove_UE(&ctxt); + + if(remove_UEContext){ + ue_context_pP = rrc_eNB_get_ue_context( + RC.rrc[mod_id],rnti); + if(ue_context_pP){ + rrc_eNB_remove_ue_context(&ctxt,RC.rrc[mod_id], + (struct rrc_eNB_ue_context_s*) ue_context_pP); + } + } + LOG_I(RRC, "[release_UE_in_freeList] remove UE %x from freeList\n", rnti); + remove_UE_from_freelist(mod_id, rnti); + } + } +} +#endif //----------------------------------------------------------------------------- void rrc_eNB_process_RRCConnectionSetupComplete( @@ -5034,6 +5144,9 @@ rrc_enb_task( int CC_id; protocol_ctxt_t ctxt; +#ifdef UE_EXPANSION + pthread_mutex_init(&lock_ue_freelist, NULL); +#endif itti_mark_task_ready(TASK_RRC_ENB); LOG_I(RRC,"Entering main loop of RRC message task\n"); while (1) { diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 39d059d3a3..ec4a61c05f 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -167,6 +167,10 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx); #endif } + +#ifdef UE_EXPANSION + release_UE_in_freeList(eNB->Mod_id); +#endif // UE-specific RX processing for subframe n phy_procedures_eNB_uespec_RX(eNB, proc, no_relay );