Commit 2efaf512 authored by Xu Bo's avatar Xu Bo

modify pre_scd thread and add phy_tx thread and rf_tx thread

parent b67c1691
......@@ -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);
......
......@@ -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
......
......@@ -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;
......
......@@ -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);
......
......@@ -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
......
......@@ -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
}
......
......@@ -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;
......
......@@ -760,6 +760,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP,
}
#if (!defined(UE_EXPANSION_SIM2)) &&(!defined(UE_EXPANSION))
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES,
NOT_A_RNTI, frameP, subframeP,
module_idP);
......@@ -767,6 +768,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP,
rrc_rx_tx(&ctxt, 0, // eNB index, unused in eNB
CC_id);
#endif
#if defined(Rel10) || defined(Rel14)
......
......@@ -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);
......@@ -1048,8 +1058,12 @@ schedule_ue_spec(module_id_t module_idP,
header_len_dtch = 0;
header_len_dtch_last = 0; // the header length of the last mac sdu
// lcid has to be sorted before the actual allocation (similar struct as ue_list).
#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2)
lcid = DTCH;
{
#else
for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) {
#endif
// TBD: check if the lcid is active
header_len_dtch += 3;
......@@ -1251,6 +1265,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, //
......
......@@ -107,4 +107,12 @@ extern int last_dlsch_ue_id[MAX_NUM_CCs];
extern int last_ulsch_ue_id[MAX_NUM_CCs];
#endif
#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2)
extern uint16_t pre_nb_rbs_required[2][MAX_NUM_CCs][NUMBER_OF_UE_MAX];
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];
#endif
#endif //DEF_H
......@@ -119,8 +119,11 @@ store_dlsch_buffer(module_id_t Mod_id, frame_t frameP,
rnti = UE_RNTI(Mod_id, UE_id);
#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2)
for (i = DCCH; i <=DTCH; i++) { // loop over DCCH, DCCH1 and DTCH
#else
for (i = 0; i < MAX_NUM_LCID; i++) { // loop over all the logical channels
#endif
rlc_status =
mac_rlc_status_ind(Mod_id, rnti, Mod_id, frameP, subframeP,
......@@ -544,6 +547,69 @@ void sort_UEs(module_id_t Mod_idP, int frameP, sub_frame_t subframeP)
#endif
}
#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=0,UE_id, lc_id, N_RB_DL;
UE_TEMPLATE UE_template;
eNB_UE_STATS *eNB_UE_stats;
rnti_t rnti;
mac_rlc_status_resp_t rlc_status;
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)
continue;
// store dlsch buffer
// clear logical channel interface variables
UE_template.dl_buffer_total = 0;
rnti = UE_RNTI(module_idP, UE_id);
for (lc_id = DCCH; lc_id <= DTCH; lc_id++) {
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_total += rlc_status.bytes_in_buffer; //storing the total dlsch buffer
}
// 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
eNB_UE_stats = &pre_scd_eNB_UE_stats[CC_id][UE_id];
eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]];
if (UE_template.dl_buffer_total > 0) {
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);
}
}
}
#endif
#ifdef UE_EXPANSION
int cc_id_end(uint8_t *cc_id_flag )
{
......@@ -1007,6 +1073,7 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id,
}
}
#if (!defined(UE_EXPANSION_SIM2)) &&(!defined(UE_EXPANSION))
// Store the DLSCH buffer for each logical channel
store_dlsch_buffer(Mod_id, frameP, subframeP);
......@@ -1015,6 +1082,9 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id,
// Calculate the number of RBs required by each UE on the basis of logical channel's buffer
assign_rbs_required(Mod_id, frameP, subframeP, nb_rbs_required,
min_rb_unit);
#else
memcpy(nb_rbs_required, pre_nb_rbs_required[dlsch_ue_select_tbl_in_use] , sizeof(uint16_t)*MAX_NUM_CCs*NUMBER_OF_UE_MAX);
#endif
#ifdef UE_EXPANSION
dlsch_scheduler_pre_ue_select(Mod_id,frameP,subframeP, mbsfn_flag,nb_rbs_required,dlsch_ue_select);
......
......@@ -227,6 +227,13 @@ void dlsch_scheduler_pre_processor_allocate (module_id_t Mod_id,
unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],
unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]);
#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2)
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]);
#endif
/* \brief Function to trigger the eNB scheduling procedure. It is called by PHY at the beginning of each subframe, \f$n$\f
and generates all DLSCH allocations for subframe \f$n\f$ and ULSCH allocations for subframe \f$n+k$\f.
@param Mod_id Instance ID of eNB
......
......@@ -151,4 +151,12 @@ int last_dlsch_ue_id[MAX_NUM_CCs] = {-1};
int last_ulsch_ue_id[MAX_NUM_CCs] = {-1};
#endif
#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2)
uint16_t pre_nb_rbs_required[2][MAX_NUM_CCs][NUMBER_OF_UE_MAX];
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];
#endif
#endif
......@@ -43,6 +43,10 @@
#include "rrc_eNB_UE_context.h"
#include "common/ran_context.h"
#if defined(ENABLE_USE_MME)
# include "rrc_eNB_S1AP.h"
#endif
#ifdef LOCALIZATION
#include <sys/time.h>
#endif
......
......@@ -188,9 +188,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 );
......
......@@ -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;
......@@ -1396,6 +1411,15 @@ static void* ru_thread( void* param ) {
// set default return value
ru_thread_status = 0;
#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2)
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);
......@@ -1485,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
......@@ -1502,6 +1550,34 @@ static void* ru_thread( void* param ) {
// If this proc is to provide synchronization, do so
wakeup_slaves(proc);
#if defined(UE_EXPANSION) || defined(UE_EXPANSION_SIM2)
new_dlsch_ue_select_tbl_in_use = dlsch_ue_select_tbl_in_use;
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);
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->proc.instance_pre_scd++;
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( 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->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
// wakeup all eNB processes waiting for this RU
if (ru->num_eNB>0) wakeup_eNBs(ru);
......@@ -1509,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);
......@@ -1518,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
}
......@@ -1609,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) {
......@@ -1679,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;
......@@ -1691,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 );
......@@ -2107,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
}
......@@ -1364,6 +1364,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);
}
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment