Skip to content
Snippets Groups Projects
lte-enb.c 52.4 KiB
Newer Older
    LOG_I(PHY, "Destroying prach mutex/cond\n");
    pthread_mutex_destroy( &proc->mutex_prach);
    pthread_cond_destroy( &proc->cond_prach );
    proc->instance_cnt_prach_br = 0;
    pthread_cond_signal( &proc->cond_prach_br );
    pthread_join( proc->pthread_prach_br, (void **)&status );
    pthread_mutex_destroy( &proc->mutex_prach_br);
    pthread_cond_destroy( &proc->cond_prach_br );
    LOG_I(PHY, "Destroying UL_INFO mutex\n");
    pthread_mutex_destroy(&eNB->UL_INFO_mutex);

    if ((get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) && NFAPI_MODE!=NFAPI_MODE_VNF) {
      LOG_I(PHY, "Joining L1_proc mutex/cond\n");
      pthread_join( L1_proc->pthread, (void **)&status );
      LOG_I(PHY, "Joining L1_proc_tx mutex/cond\n");
      pthread_join( L1_proc_tx->pthread, (void **)&status );
    }

    LOG_I(PHY, "Destroying L1_proc mutex/cond\n");
    pthread_mutex_destroy( &L1_proc->mutex );
    pthread_cond_destroy( &L1_proc->cond );
    pthread_mutex_destroy( &L1_proc->mutex_RUs );
    pthread_cond_destroy( &L1_proc->cond_RUs );
    LOG_I(PHY, "Destroying L1_proc_tx mutex/cond\n");
    pthread_mutex_destroy( &L1_proc_tx->mutex );
    pthread_cond_destroy( &L1_proc_tx->cond );
    pthread_mutex_destroy( &L1_proc_tx->mutex_RUs );
    pthread_cond_destroy( &L1_proc_tx->cond_RUs );
    pthread_attr_destroy(&proc->attr_prach);
    pthread_attr_destroy(&proc->attr_asynch_rxtx);
    pthread_attr_destroy(&L1_proc->attr);
    pthread_attr_destroy(&L1_proc_tx->attr);
    pthread_mutex_destroy(&proc->mutex_RU_PRACH_br);
    pthread_attr_destroy(&proc->attr_prach_br);
  }
}

static void reset_opp_meas(PHY_VARS_eNB *eNB)
{
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
  reset_meas(&softmodem_stats_rxtx_sf);
  reset_meas(&softmodem_stats_rx_sf);
  reset_meas(&eNB->ulsch_decoding_stats);
  reset_meas(&eNB->dlsch_turbo_encoding_preperation_stats);
  reset_meas(&eNB->dlsch_turbo_encoding_segmentation_stats);
  reset_meas(&eNB->dlsch_encoding_stats);
  reset_meas(&eNB->dlsch_turbo_encoding_stats);
  reset_meas(&eNB->dlsch_interleaving_stats);
  reset_meas(&eNB->dlsch_rate_matching_stats);
  reset_meas(&eNB->dlsch_modulation_stats);
}

static void print_opp_meas(PHY_VARS_eNB *eNB)
{
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);

    print_meas(&softmodem_stats_rxtx_sf,"[eNB][total_phy_proc_rxtx]",NULL, NULL);
    print_meas(&softmodem_stats_rx_sf,"[eNB][total_phy_proc_rx]",NULL,NULL);
    if (eNB->ulsch_decoding_stats.trials > 0)
      print_meas(&eNB->ulsch_decoding_stats, "ulsch_decoding", NULL, NULL);

    if (eNB->dlsch_encoding_stats.trials > 0) {
      print_meas(&eNB->dlsch_turbo_encoding_preperation_stats, "dlsch_coding_crc", NULL, NULL);
      print_meas(&eNB->dlsch_turbo_encoding_segmentation_stats, "dlsch_segmentation", NULL, NULL);
      print_meas(&eNB->dlsch_encoding_stats, "dlsch_encoding", NULL, NULL);
      print_meas(&eNB->dlsch_turbo_encoding_stats, "turbo_encoding", NULL, NULL);
      print_meas(&eNB->dlsch_interleaving_stats, "turbo_interleaving", NULL, NULL);
      print_meas(&eNB->dlsch_rate_matching_stats, "turbo_rate_matching", NULL, NULL);
    }

    print_meas(&eNB->dlsch_modulation_stats, "dlsch_modulation", NULL, NULL);
}

void free_transport(PHY_VARS_eNB *eNB) {
  for (int i=0; i<NUMBER_OF_DLSCH_MAX; i++) {
    LOG_D(PHY, "Freeing Transport Channel Buffers for DLSCH %d\n",i);

    for (int j=0; j<2; j++) free_eNB_dlsch(eNB->dlsch[i][j]);
  }
  for (int i=0;i<NUMBER_OF_ULSCH_MAX;i++) {
    LOG_D(PHY, "Freeing Transport Channel Buffer for ULSCH %d\n",i);
    free_eNB_ulsch(eNB->ulsch[i]);
  }
}


void init_transport(PHY_VARS_eNB *eNB) {
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  LOG_I(PHY, "Initialise transport\n");

  if (NFAPI_MODE!=NFAPI_MODE_VNF) {
    for (int i=0;i<NUMBER_OF_DLSCH_MAX; i++) {
      LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH %d/%d/%d\n",i,NUMBER_OF_DLSCH_MAX,(i-NUMBER_OF_DLSCH_MAX)<0);

      for (int j=0; j<2; j++) {
        eNB->dlsch[i][j] = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL,0,fp);
        LOG_I(PHY,"eNB->dlsch[%d][%d] %p\n",i,j,eNB->dlsch[i][j]);
        if (!eNB->dlsch[i][j]) {
          LOG_E(PHY,"Can't get eNB dlsch structures for DLSCH %d \n", i);
          exit(-1);
        } else {
          eNB->dlsch[i][j]->rnti=0;
          LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,eNB->dlsch[i][j], eNB->dlsch[i][j]->rnti);
        }
      }
    }
    for (int i=0;i<NUMBER_OF_ULSCH_MAX; i++) {

      LOG_I(PHY,"Allocating Transport Channel Buffers for ULSCH %d/%d\n",i,NUMBER_OF_ULSCH_MAX);
      eNB->ulsch[i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,fp->N_RB_UL, 0);

      if (!eNB->ulsch[i]) {
        LOG_E(PHY,"Can't get eNB ulsch structures\n");
        exit(-1);
      }
    }

    eNB->dlsch_SI  = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp);
    LOG_D(PHY,"eNB %d.%d : SI %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_SI);
    eNB->dlsch_ra  = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp);
    LOG_D(PHY,"eNB %d.%d : RA %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_ra);
    eNB->dlsch_MCH = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp);
    LOG_D(PHY,"eNB %d.%d : MCH %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_MCH);
  }

  eNB->rx_total_gain_dB=130;

  for(int i=0; i<NUMBER_OF_UE_MAX; i++)
    eNB->mu_mimo_mode[i].dl_pow_off = 2;

  eNB->check_for_total_transmissions = 0;
  eNB->check_for_MUMIMO_transmissions = 0;
  eNB->FULL_MUMIMO_transmissions = 0;
  eNB->check_for_SUMIMO_transmissions = 0;
  fp->pucch_config_common.deltaPUCCH_Shift = 1;
  if (eNB->use_DTX == 0) fill_subframe_mask(eNB);
  
}


void init_eNB_afterRU(void) {
  int inst,CC_id,i;
  PHY_VARS_eNB *eNB;
  LOG_I(PHY,"%s() RC.nb_inst:%d\n", __FUNCTION__, RC.nb_inst);

  for (inst=0; inst<RC.nb_inst; inst++) {
    LOG_I(PHY,"RC.nb_CC[inst]:%d\n", RC.nb_CC[inst]);

    for (CC_id=0; CC_id<RC.nb_CC[inst]; CC_id++) {
      LOG_I(PHY,"RC.nb_CC[inst:%d][CC_id:%d]:%p\n", inst, CC_id, RC.eNB[inst][CC_id]);
      eNB                                  =  RC.eNB[inst][CC_id];
     // map antennas and PRACH signals to eNB RX
      LOG_I(PHY,"Mapping RX ports from %d RUs to eNB %d\n",eNB->num_RU,eNB->Mod_id);
      eNB->frame_parms.nb_antennas_rx       = 0;
      LOG_I(PHY,"eNB->num_RU:%d\n", eNB->num_RU);     
      if (NFAPI_MODE==NFAPI_MODE_PNF) AssertFatal(eNB->num_RU>0,"Number of RU attached to eNB %d is      zero\n",eNB->Mod_id);
      for (int ru_id=0; ru_id<eNB->num_RU; ru_id++) 
         eNB->frame_parms.nb_antennas_rx    += eNB->RU_list[ru_id]->nb_rx;
      phy_init_lte_eNB(eNB,0,0);
      LOG_I(PHY,"Overwriting eNB->prach_vars.rxsigF[0]:%p\n", eNB->prach_vars.rxsigF[0]);
      eNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *));

      for (int ce_level=0; ce_level<4; ce_level++) {
        LOG_I(PHY,"Overwriting eNB->prach_vars_br.rxsigF.rxsigF[0]:%p\n", eNB->prach_vars_br.rxsigF[ce_level]);
        eNB->prach_vars_br.rxsigF[ce_level] = (int16_t **)malloc16(64*sizeof(int16_t *));
      }


      for (int ru_id=0,aa=0; ru_id<eNB->num_RU; ru_id++) {

        AssertFatal(eNB->RU_list[ru_id]->common.rxdataF!=NULL,
                    "RU %d : common.rxdataF is NULL\n",
                    eNB->RU_list[ru_id]->idx);
        AssertFatal(eNB->RU_list[ru_id]->prach_rxsigF!=NULL,
                    "RU %d : prach_rxsigF is NULL\n",
                    eNB->RU_list[ru_id]->idx);

        for (i=0; i<eNB->RU_list[ru_id]->nb_rx; aa++,i++) {
          LOG_I(PHY,"Attaching RU %d antenna %d to eNB antenna %d\n",eNB->RU_list[ru_id]->idx,i,aa);
          eNB->prach_vars.rxsigF[0][aa]    =  eNB->RU_list[ru_id]->prach_rxsigF[0][i];

          for (int ce_level=0; ce_level<4; ce_level++)
            eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[ru_id]->prach_rxsigF_br[ce_level][i];

          eNB->common_vars.rxdataF[aa]     =  eNB->RU_list[ru_id]->common.rxdataF[i];
        }
      }

      /* TODO: review this code, there is something wrong.
       * In monolithic mode, we come here with nb_antennas_rx == 0
       * (not tested in other modes).
       */
      if (eNB->frame_parms.nb_antennas_rx < 1) {
        LOG_I(PHY, "%s() ************* DJP ***** eNB->frame_parms.nb_antennas_rx:%d - GOING TO HARD CODE TO 1", __FUNCTION__, eNB->frame_parms.nb_antennas_rx);
        eNB->frame_parms.nb_antennas_rx = 1;
      } else {
        //LOG_I(PHY," Delete code\n");
      }

      if (eNB->frame_parms.nb_antennas_tx < 1) {
        LOG_I(PHY, "%s() ************* DJP ***** eNB->frame_parms.nb_antennas_tx:%d - GOING TO HARD CODE TO 1", __FUNCTION__, eNB->frame_parms.nb_antennas_tx);
        eNB->frame_parms.nb_antennas_tx = 1;
      } else {
        //LOG_I(PHY," Delete code\n");
      }

      AssertFatal(eNB->frame_parms.nb_antennas_rx >0,
                  "inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx);
      LOG_I(PHY,"inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx);
      init_transport(eNB);
      //init_precoding_weights(RC.eNB[inst][CC_id]);
    }

    init_eNB_proc(inst);
  }

  for (int ru_id=0; ru_id<RC.nb_RU; ru_id++) {
    AssertFatal(RC.ru[ru_id]!=NULL,"ru_id %d is null\n",ru_id);
    RC.ru[ru_id]->wakeup_rxtx         = wakeup_rxtx;
    RC.ru[ru_id]->wakeup_prach_eNB    = wakeup_prach_eNB;
    RC.ru[ru_id]->wakeup_prach_eNB_br = wakeup_prach_eNB_br;
    RC.ru[ru_id]->eNB_top             = eNB_top;
  }
}


void init_eNB(int single_thread_flag,
              int wait_for_sync) {
  int CC_id;
  int inst;
  PHY_VARS_eNB *eNB;
  LOG_I(PHY,"[lte-softmodem.c] eNB structure about to allocated RC.nb_L1_inst:%d RC.nb_L1_CC[0]:%d\n",RC.nb_L1_inst,RC.nb_L1_CC[0]);

  if (RC.eNB == NULL) RC.eNB = (PHY_VARS_eNB ** *) malloc(RC.nb_L1_inst*sizeof(PHY_VARS_eNB **));

  LOG_I(PHY,"[lte-softmodem.c] eNB structure RC.eNB allocated\n");

  for (inst=0; inst<RC.nb_L1_inst; inst++) {
    if (RC.eNB[inst] == NULL) RC.eNB[inst] = (PHY_VARS_eNB **) malloc(RC.nb_CC[inst]*sizeof(PHY_VARS_eNB *));

    for (CC_id=0; CC_id<RC.nb_L1_CC[inst]; CC_id++) {
      if (RC.eNB[inst][CC_id] == NULL) 
         RC.eNB[inst][CC_id] = (PHY_VARS_eNB *) calloc(1,sizeof(PHY_VARS_eNB));

      eNB                     = RC.eNB[inst][CC_id];
      eNB->abstraction_flag   = 0;
      eNB->single_thread_flag = single_thread_flag;
      LOG_I(PHY,"Initializing eNB %d CC_id %d single_thread_flag:%d\n",inst,CC_id,single_thread_flag);
      LOG_I(PHY,"Initializing eNB %d CC_id %d\n",inst,CC_id);
      LOG_I(PHY,"Registering with MAC interface module\n");
      AssertFatal((eNB->if_inst         = IF_Module_init(inst))!=NULL,"Cannot register interface");
      eNB->if_inst->schedule_response   = schedule_response;
      eNB->if_inst->PHY_config_req      = phy_config_request;
      eNB->if_inst->PHY_config_update_sib2_req      = phy_config_update_sib2_request;
      eNB->if_inst->PHY_config_update_sib13_req      = phy_config_update_sib13_request;
      memset((void *)&eNB->UL_INFO,0,sizeof(eNB->UL_INFO));
      memset((void *)&eNB->Sched_INFO,0,sizeof(eNB->Sched_INFO));
      LOG_I(PHY,"Setting indication lists\n");
      eNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list   = eNB->rx_pdu_list;
      eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = eNB->crc_pdu_list;
      eNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = eNB->sr_pdu_list;
      eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = eNB->harq_pdu_list;
      eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_pdu_list = eNB->cqi_pdu_list;
      eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_raw_pdu_list = eNB->cqi_raw_pdu_list;
      eNB->prach_energy_counter = 0;
    }
  }
  LOG_I(PHY,"[lte-softmodem.c] eNB structure allocated\n");
}


void stop_eNB(int nb_inst) {
  for (int inst=0; inst<nb_inst; inst++) {
    LOG_I(PHY,"Killing eNB %d processing threads\n",inst);
    kill_eNB_proc(inst);
  }
}