diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 6fce45ab1ee720e6a67a30171d91cce395275f9a..459d321b3ee43663beb9d8a9486d8e79458a7d59 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<<rel8->harq_process); dlsch1->harq_mask |= (1<<rel8->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<<rel8->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<<rel8->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<<rel8->harq_process); dlsch1->harq_mask |= (1<<rel8->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<<rel8->harq_process); dlsch1->harq_mask |= (1<<rel8->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<<rel8->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<<rel8->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<<rel13->harq_process); diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h index f1f4be3072c86b166168fc906a061b599aa0cfc5..b293e56b87950d7a5bffc5d92f72ecd9e964730d 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 dbfae80840c4c76fe605fa11fb8023cfb4877b13..7482524d41f7ae03cd2e35c1cf65d0cf9773e6e1 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 d90f4c66d255158e35a820602f3140c55e8b69bc..83392b18a9cf3f4e4afa28856f4de0ab6992aff9 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 c1d3ba7ce63bcf8bbff80fab466cfbb3f75ace63..6f91b61375012d9eddcef884968fddaa4999469f 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 c93934b011cb54ebf3aa3160be979247f5b5c638..dbce91776d56d8fc8ee9fd0be225502d4e026bce 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 3debfee997d832b903548dab3949529cde258394..8500cd8b9b8cbf705fe9f5a344075c87a9400500 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 1b3a85e5eecc21774b3f56907a7b21f1b6533869..7ed20d55ae239be92592fc5e091cdcc8448c1f24 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_id<MAX_NUM_CCs; CC_id++) { LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n",CC_id); @@ -1254,6 +1264,12 @@ schedule_ue_spec(module_id_t module_idP, post_padding = TBS - sdu_length_total - header_len_dcch - header_len_dtch - ta_len; // 1 is for the postpadding header } +#ifdef UE_EXPANSION + while((!oai_exit)&&(phy_tx_txdataF_end == 0)){ + nanosleep(&time_req,&time_rem); + continue; + } +#endif offset = generate_dlsch_header((unsigned char *) UE_list->DLSCH_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 9f29af5b9bae85ef5e32bd1a4973605848f95d6a..790f89d2c724a89db86795c2d5431dea0dde3755 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 bedd37165cc4697965a7178758d4f04b4e80bc0e..ffe24cae25de9aa62d7ee2f51f3f9fadef23ea4b 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<NB_RB;nb_rb+=step_size){ + tmp_TBS = TBStable[i_TBS][nb_rb-1]>>3; + if(TBS<tmp_TBS)return(nb_rb); + } + return NB_RB; +} void pre_scd_nb_rbs_required( module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, int min_rb_unit[MAX_NUM_CCs], uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX]) { - int CC_id,UE_id, lc_id,i, j, tmp, N_RB_DL;; + int CC_id=0,UE_id, lc_id, N_RB_DL; UE_TEMPLATE UE_template; - eNB_UE_STATS *eNB_UE_stats, *eNB_UE_stats_i, *eNB_UE_stats_j; + eNB_UE_STATS *eNB_UE_stats; rnti_t rnti; mac_rlc_status_resp_t rlc_status; - uint16_t TBS = 0; - + uint16_t step_size=2; + + N_RB_DL = to_prb(RC.mac[module_idP]->common_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 <NUMBER_OF_UE_MAX; UE_id++) { if (pre_scd_activeUE[UE_id] != TRUE) @@ -571,132 +584,27 @@ void pre_scd_nb_rbs_required( module_id_t module_idP, // clear logical channel interface variables UE_template.dl_buffer_total = 0; - UE_template.dl_pdus_total = 0; rnti = UE_RNTI(module_idP, UE_id); for (lc_id = DCCH; lc_id <= DTCH; lc_id++) { - UE_template.dl_buffer_info[lc_id] = 0; - UE_template.dl_pdus_in_buffer[lc_id] = 0; - UE_template.dl_buffer_head_sdu_creation_time[lc_id] = 0; - UE_template.dl_buffer_head_sdu_remaining_size_to_send[lc_id] = 0; rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, lc_id, 0); - UE_template.dl_buffer_info[lc_id] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel - UE_template.dl_pdus_in_buffer[lc_id] = rlc_status.pdus_in_buffer; - UE_template.dl_buffer_head_sdu_creation_time[lc_id] = rlc_status.head_sdu_creation_time; - UE_template.dl_buffer_head_sdu_creation_time_max = - cmax(UE_template.dl_buffer_head_sdu_creation_time_max, - rlc_status.head_sdu_creation_time); - UE_template.dl_buffer_head_sdu_remaining_size_to_send[lc_id] = - rlc_status.head_sdu_remaining_size_to_send; - UE_template.dl_buffer_head_sdu_is_segmented[lc_id] = rlc_status.head_sdu_is_segmented; - UE_template.dl_buffer_total += UE_template.dl_buffer_info[lc_id]; //storing the total dlsch buffer - UE_template.dl_pdus_total += UE_template.dl_pdus_in_buffer[lc_id]; - -#ifdef DEBUG_eNB_SCHEDULER - /* note for dl_buffer_head_sdu_remaining_size_to_send[i] : - * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent - */ - if (UE_template.dl_buffer_info[lc_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 b6db7fe79e5b1aff6e67e6d7114034207cbea621..01ece20d482dcd087902d60f1eef7b60cb2d5be0 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 9b46ae7f32f5a1db02b739285602a12d93207e06..39d059d3a312dd2a39107deec4a307011e3bd1f5 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 430f1e64268ff79544df59dbb423f488fb17b3bf..18d9cd42fca12e2599281d022a26f1ef0eeac75e 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 e90fc4335c5edd68369163e1cde3fcc9f474dc0b..e8b204a7b4a8201ee97c75aae2463aec3f202f66 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<RC.nb_RU;ru_id++) { + stop_ru(RC.ru[ru_id]); + } +#endif stop_eNB(1); } diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h index 44e35c88a385319e896142e77ec05d5a62a9eb01..0e5e6b6081d352e13753acd8a9906bfeb7de02c3 100644 --- a/targets/RT/USER/lte-softmodem.h +++ b/targets/RT/USER/lte-softmodem.h @@ -244,6 +244,9 @@ extern void kill_eNB_proc(int inst); // In lte-ru.c extern void init_RU(const char*); +#ifdef UE_EXPANSION +extern void stop_ru(RU_t *ru); +#endif // In lte-ue.c extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg);