nr-gnb.c 21.8 KB
Newer Older
laurent's avatar
laurent committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

/*! \file lte-enb.c
 * \brief Top-level threads for gNodeB
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
 * \date 2012
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
 * \note
 * \warning
 */

#define _GNU_SOURCE
#include <pthread.h>

#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all

#include "assertions.h"
Laurent's avatar
Laurent committed
39 40
#include <common/utils/LOG/log.h>
#include <common/utils/system.h>
laurent's avatar
laurent committed
41 42 43 44 45 46 47 48 49

#include "PHY/types.h"

#include "PHY/INIT/phy_init.h"

#include "PHY/defs_gNB.h"
#include "SCHED/sched_eNB.h"
#include "SCHED_NR/sched_nr.h"
#include "SCHED_NR/fapi_nr_l1.h"
cig's avatar
cig committed
50
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
51
#include "PHY/MODULATION/nr_modulation.h"
52
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
laurent's avatar
laurent committed
53 54 55 56 57 58 59 60 61 62 63 64 65

#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all

#include "../../ARCH/COMMON/common_lib.h"

//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all

#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"

#include "PHY/phy_extern.h"

66
#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
laurent's avatar
laurent committed
67 68 69 70 71 72 73 74 75
#include "RRC/LTE/rrc_extern.h"
#include "PHY_INTERFACE/phy_interface.h"
#include "common/utils/LOG/log_extern.h"
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "enb_config.h"
76
#include "gnb_paramdef.h"
laurent's avatar
laurent committed
77 78 79 80 81 82


#ifndef OPENAIR2
  #include "UTIL/OTG/otg_extern.h"
#endif

83 84
#include "s1ap_eNB.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"
85
#include <executables/softmodem-common.h>
laurent's avatar
laurent committed
86 87

#include "T.h"
Mahesh's avatar
Mahesh committed
88
#include "nfapi/oai_integration/vendor_ext.h"
Sakthivel Velumani's avatar
Sakthivel Velumani committed
89
#include "executables/softmodem-common.h"
Laurent THOMAS's avatar
Laurent THOMAS committed
90
#include <nfapi/oai_integration/nfapi_pnf.h>
91
#include <openair1/PHY/NR_TRANSPORT/nr_ulsch.h>
rmagueta's avatar
rmagueta committed
92
#include <openair1/PHY/NR_TRANSPORT/nr_dlsch.h>
rmagueta's avatar
rmagueta committed
93
#include <PHY/NR_ESTIMATION/nr_ul_estimation.h>
laurent's avatar
laurent committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
//#define DEBUG_THREADS 1

//#define USRP_DEBUG 1
// Fix per CC openair rf/if device update
// extern openair0_device openair0;


//pthread_t                       main_gNB_thread;

time_stats_t softmodem_stats_mt; // main thread
time_stats_t softmodem_stats_hw; //  hw acquisition
time_stats_t softmodem_stats_rxtx_sf; // total tx time
time_stats_t nfapi_meas; // total tx time
time_stats_t softmodem_stats_rx_sf; // total rx time


110
#include "executables/thread-common.h"
laurent's avatar
laurent committed
111 112 113 114 115 116


//#define TICK_TO_US(ts) (ts.diff)
#define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials)


117
void tx_func(void *param) {
laurent's avatar
laurent committed
118

119
  processingData_L1tx_t *info = (processingData_L1tx_t *) param;
120
  PHY_VARS_gNB *gNB = info->gNB;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
121 122
  int frame_tx = info->frame;
  int slot_tx = info->slot;
laurent's avatar
laurent committed
123

124 125 126 127
  phy_procedures_gNB_TX(info,
                        frame_tx,
                        slot_tx,
                        1);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
128
  info->slot = -1;
rmagueta's avatar
rmagueta committed
129
  //if ((frame_tx&127) == 0) dump_pdsch_stats(fd,gNB);
130

131 132 133 134 135
  // If the later of the 2 L1 tx thread finishes first,
  // we wait for the earlier one to finish and start the RU thread
  // to avoid realtime issues with USRP

  // Start RU TX processing.
136
  notifiedFIFO_elt_t *res;
137 138
  res = pullTpool(gNB->resp_RU_tx, gNB->threadPool);
  processingData_RU_t *syncMsg = (processingData_RU_t *)NotifiedFifoData(res);
139 140 141 142 143 144
  LOG_D(PHY,"waiting for previous tx to finish, next slot %d,%d\n",syncMsg->next_slot,slot_tx);
  while (syncMsg->next_slot != slot_tx) {
    pushNotifiedFIFO(gNB->resp_RU_tx, res);
    res = pullTpool(gNB->resp_RU_tx, gNB->threadPool);
    syncMsg = (processingData_RU_t *)NotifiedFifoData(res);
  }
145
  LOG_D(PHY,"previous tx finished, next slot %d,%d\n",syncMsg->next_slot,slot_tx);
146 147
  syncMsg->frame_tx = frame_tx;
  syncMsg->slot_tx = slot_tx;
148
  syncMsg->next_slot = get_next_downlink_slot(gNB, &gNB->gNB_config, frame_tx, slot_tx);
149 150 151 152 153
  syncMsg->timestamp_tx = info->timestamp_tx;
  syncMsg->ru = gNB->RU_list[0];
  res->key = slot_tx;
  pushTpool(gNB->threadPool, res);
}
laurent's avatar
laurent committed
154

155
void rx_func(void *param) {
156

157 158 159 160 161 162
  processingData_L1_t *info = (processingData_L1_t *) param;
  PHY_VARS_gNB *gNB = info->gNB;
  int frame_rx = info->frame_rx;
  int slot_rx = info->slot_rx;
  int frame_tx = info->frame_tx;
  int slot_tx = info->slot_tx;
163
  sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe;
164 165
  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;

laurent's avatar
laurent committed
166 167 168
  start_meas(&softmodem_stats_rxtx_sf);

  // *******************************************************************
169

170
  if (NFAPI_MODE == NFAPI_MODE_PNF) {
laurent's avatar
laurent committed
171
    // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick
172
    //LOG_D(PHY, "oai_nfapi_slot_ind(frame:%u, slot:%d) ********\n", frame_rx, slot_rx);
laurent's avatar
laurent committed
173
    start_meas(&nfapi_meas);
174
    handle_nr_slot_ind(frame_rx, slot_rx);
laurent's avatar
laurent committed
175 176
    stop_meas(&nfapi_meas);

177
    /*if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus||
laurent's avatar
laurent committed
178 179
        gNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs ||
        gNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs ||
180
        gNB->UL_INFO.rach_ind.number_of_pdus ||
laurent's avatar
laurent committed
181 182
        gNB->UL_INFO.cqi_ind.number_of_cqis
       ) {
183
      LOG_D(PHY, "UL_info[rx_ind:%05d:%d harqs:%05d:%d crcs:%05d:%d rach_pdus:%0d.%d:%d cqis:%d] RX:%04d%d TX:%04d%d \n",
laurent's avatar
laurent committed
184 185 186
            NFAPI_SFNSF2DEC(gNB->UL_INFO.rx_ind.sfn_sf),   gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus,
            NFAPI_SFNSF2DEC(gNB->UL_INFO.harq_ind.sfn_sf), gNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs,
            NFAPI_SFNSF2DEC(gNB->UL_INFO.crc_ind.sfn_sf),  gNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs,
187
            gNB->UL_INFO.rach_ind.sfn, gNB->UL_INFO.rach_ind.slot,gNB->UL_INFO.rach_ind.number_of_pdus,
laurent's avatar
laurent committed
188
            gNB->UL_INFO.cqi_ind.number_of_cqis,
189 190
            frame_rx, slot_rx,
            frame_tx, slot_tx);
191
    }*/
laurent's avatar
laurent committed
192 193
  }
  // ****************************************
194

195
  T(T_GNB_PHY_DL_TICK, T_INT(gNB->Mod_id), T_INT(frame_tx), T_INT(slot_tx));
196

197 198 199 200 201 202 203 204 205
  /* hack to remove UEs */
  extern int rnti_to_remove[10];
  extern volatile int rnti_to_remove_count;
  extern pthread_mutex_t rnti_to_remove_mutex;
  if (pthread_mutex_lock(&rnti_to_remove_mutex)) exit(1);
  int up_removed = 0;
  int down_removed = 0;
  int pucch_removed = 0;
  for (int i = 0; i < rnti_to_remove_count; i++) {
rmagueta's avatar
rmagueta committed
206
    LOG_W(NR_PHY, "to remove rnti %d\n", rnti_to_remove[i]);
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
    void clean_gNB_ulsch(NR_gNB_ULSCH_t *ulsch);
    void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch);
    int j;
    for (j = 0; j < NUMBER_OF_NR_ULSCH_MAX; j++)
      if (gNB->ulsch[j][0]->rnti == rnti_to_remove[i]) {
        gNB->ulsch[j][0]->rnti = 0;
        gNB->ulsch[j][0]->harq_mask = 0;
        //clean_gNB_ulsch(gNB->ulsch[j][0]);
        int h;
        for (h = 0; h < NR_MAX_ULSCH_HARQ_PROCESSES; h++) {
          gNB->ulsch[j][0]->harq_processes[h]->status = SCH_IDLE;
          gNB->ulsch[j][0]->harq_processes[h]->round  = 0;
          gNB->ulsch[j][0]->harq_processes[h]->handled = 0;
        }
        up_removed++;
      }
    for (j = 0; j < NUMBER_OF_NR_PUCCH_MAX; j++)
      if (gNB->pucch[j]->active > 0 &&
          gNB->pucch[j]->pucch_pdu.rnti == rnti_to_remove[i]) {
        gNB->pucch[j]->active = 0;
        gNB->pucch[j]->pucch_pdu.rnti = 0;
        pucch_removed++;
      }
#if 0
    for (j = 0; j < NUMBER_OF_NR_PDCCH_MAX; j++)
      gNB->pdcch_pdu[j].frame = -1;
    for (j = 0; j < NUMBER_OF_NR_PDCCH_MAX; j++)
      gNB->ul_pdcch_pdu[j].frame = -1;
    for (j = 0; j < NUMBER_OF_NR_PRACH_MAX; j++)
      gNB->prach_vars.list[j].frame = -1;
#endif
  }
rmagueta's avatar
rmagueta committed
239
  if (rnti_to_remove_count) LOG_W(NR_PHY, "to remove rnti_to_remove_count=%d, up_removed=%d down_removed=%d pucch_removed=%d\n", rnti_to_remove_count, up_removed, down_removed, pucch_removed);
240 241 242
  rnti_to_remove_count = 0;
  if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1);

243 244 245 246 247 248 249
  // RX processing
  int tx_slot_type         = nr_slot_select(cfg,frame_tx,slot_tx);
  int rx_slot_type         = nr_slot_select(cfg,frame_rx,slot_rx);

  if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) {
    // UE-specific RX processing for subframe n
    // TODO: check if this is correct for PARALLEL_RU_L1_TRX_SPLIT
250 251

    // Do PRACH RU processing
252
    L1_nr_prach_procedures(gNB,frame_rx,slot_rx);
253

254
    //apply the rx signal rotation here
255 256 257 258 259 260 261 262
    for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) {
      apply_nr_rotation_ul(&gNB->frame_parms,
                           gNB->common_vars.rxdataF[aa],
                           slot_rx,
                           0,
                           gNB->frame_parms.Ncp==EXTENDED?12:14,
                           gNB->frame_parms.ofdm_symbol_size);
    }
263 264 265
    phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
  }

266
  stop_meas( &softmodem_stats_rxtx_sf );
267
  LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx);
laurent's avatar
laurent committed
268

269 270 271 272 273 274 275 276 277 278 279
  // Call the scheduler
  start_meas(&gNB->ul_indication_stats);
  pthread_mutex_lock(&gNB->UL_INFO_mutex);
  gNB->UL_INFO.frame     = frame_rx;
  gNB->UL_INFO.slot      = slot_rx;
  gNB->UL_INFO.module_id = gNB->Mod_id;
  gNB->UL_INFO.CC_id     = gNB->CC_id;
  gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
  pthread_mutex_unlock(&gNB->UL_INFO_mutex);
  stop_meas(&gNB->ul_indication_stats);
  
280
  if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) {
281
    notifiedFIFO_elt_t *res;
282
    res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
283
    processingData_L1tx_t *syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
284
    while (syncMsg->slot != slot_tx) {
285 286 287 288
      pushNotifiedFIFO(gNB->resp_L1_tx, res);
      res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
      syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
    }
289
    syncMsg->gNB = gNB;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
290
    AssertFatal(syncMsg->slot == slot_tx, "Thread message slot and logical slot number do not match\n");
291 292 293
    syncMsg->timestamp_tx = info->timestamp_tx;
    res->key = slot_tx;
    pushTpool(gNB->threadPool, res);
laurent's avatar
laurent committed
294
  }
295
    
laurent's avatar
laurent committed
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
#if 0
  LOG_D(PHY, "rxtx:%lld nfapi:%lld phy:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ",
        softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now,
        TICK_TO_US(gNB->phy_proc),
        TICK_TO_US(gNB->phy_proc_tx),
        TICK_TO_US(gNB->phy_proc_rx),
        TICK_TO_US(gNB->rx_prach),
        TICK_TO_US(gNB->ofdm_mod_stats),
        softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now);
  LOG_D(PHY,
        "dlsch[enc:%lld mod:%lld scr:%lld rm:%lld t:%lld i:%lld] rx_dft:%lld ",
        TICK_TO_US(gNB->dlsch_encoding_stats),
        TICK_TO_US(gNB->dlsch_modulation_stats),
        TICK_TO_US(gNB->dlsch_scrambling_stats),
        TICK_TO_US(gNB->dlsch_rate_matching_stats),
        TICK_TO_US(gNB->dlsch_turbo_encoding_stats),
        TICK_TO_US(gNB->dlsch_interleaving_stats),
        TICK_TO_US(gNB->rx_dft_stats));
  LOG_D(PHY," ulsch[ch:%lld freq:%lld dec:%lld demod:%lld ru:%lld ",
        TICK_TO_US(gNB->ulsch_channel_estimation_stats),
        TICK_TO_US(gNB->ulsch_freq_offset_estimation_stats),
        TICK_TO_US(gNB->ulsch_decoding_stats),
        TICK_TO_US(gNB->ulsch_demodulation_stats),
        TICK_TO_US(gNB->ulsch_rate_unmatching_stats));
  LOG_D(PHY, "td:%lld dei:%lld dem:%lld llr:%lld tci:%lld ",
        TICK_TO_US(gNB->ulsch_turbo_decoding_stats),
        TICK_TO_US(gNB->ulsch_deinterleaving_stats),
        TICK_TO_US(gNB->ulsch_demultiplexing_stats),
        TICK_TO_US(gNB->ulsch_llr_stats),
        TICK_TO_US(gNB->ulsch_tc_init_stats));
  LOG_D(PHY, "tca:%lld tcb:%lld tcg:%lld tce:%lld l1:%lld l2:%lld]\n\n",
        TICK_TO_US(gNB->ulsch_tc_alpha_stats),
        TICK_TO_US(gNB->ulsch_tc_beta_stats),
        TICK_TO_US(gNB->ulsch_tc_gamma_stats),
        TICK_TO_US(gNB->ulsch_tc_ext_stats),
        TICK_TO_US(gNB->ulsch_tc_intl1_stats),
        TICK_TO_US(gNB->ulsch_tc_intl2_stats)
       );
#endif
}
laurent's avatar
laurent committed
336
static void *process_stats_thread(void *param) {
337

laurent's avatar
laurent committed
338
  PHY_VARS_gNB *gNB  = (PHY_VARS_gNB *)param;
339 340

  reset_meas(&gNB->dlsch_encoding_stats);
341
  reset_meas(&gNB->phy_proc_rx);
342
  reset_meas(&gNB->ul_indication_stats);
343 344
  reset_meas(&gNB->rx_pusch_stats);
  reset_meas(&gNB->ulsch_decoding_stats);
345 346 347 348 349 350

  wait_sync("process_stats_thread");

  while(!oai_exit)
  {
    sleep(1);
351 352
    print_meas(gNB->phy_proc_tx_0, "L1 Tx processing thread 0", NULL, NULL);
    print_meas(gNB->phy_proc_tx_1, "L1 Tx processing thread 1", NULL, NULL);
353 354
    print_meas(&gNB->dlsch_encoding_stats, "DLSCH encoding", NULL, NULL);
    print_meas(&gNB->phy_proc_rx, "L1 Rx processing", NULL, NULL);
355
    print_meas(&gNB->ul_indication_stats, "UL Indication", NULL, NULL);
356 357
    print_meas(&gNB->rx_pusch_stats, "PUSCH inner-receiver", NULL, NULL);
    print_meas(&gNB->ulsch_decoding_stats, "PUSCH decoding", NULL, NULL);
358 359 360 361
  }
  return(NULL);
}

362 363 364 365 366 367 368
void *nrL1_stats_thread(void *param) {
  PHY_VARS_gNB     *gNB      = (PHY_VARS_gNB *)param;
  wait_sync("L1_stats_thread");
  FILE *fd;
  while (!oai_exit) {
    sleep(1);
    fd=fopen("nrL1_stats.log","w");
369
    AssertFatal(fd!=NULL,"Cannot open nrL1_stats.log\n");
370
    dump_nr_I0_stats(fd,gNB);
371
    dump_pdsch_stats(fd,gNB);
372
    dump_pusch_stats(fd,gNB);
rmagueta's avatar
rmagueta committed
373
    //    nr_dump_uci_stats(fd,eNB,eNB->proc.L1_proc_tx.frame_tx);
374 375 376 377 378
    fclose(fd);
  }
  return(NULL);
}

Sakthivel Velumani's avatar
Sakthivel Velumani committed
379
void init_gNB_Tpool(int inst) {
laurent's avatar
laurent committed
380
  PHY_VARS_gNB *gNB;
381
  gNB = RC.gNB[inst];
382
  gNB_L1_proc_t *proc = &gNB->proc;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
383

Sakthivel Velumani's avatar
Sakthivel Velumani committed
384
  // ULSCH decoding threadpool
Sakthivel Velumani's avatar
Sakthivel Velumani committed
385
  gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
386
  int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
387
  LOG_I(PHY,"Number of threads requested in config file: %d, Number of threads available on this machine: %d\n",gNB->pusch_proc_threads,numCPU);
388
  int threadCnt = min(numCPU, gNB->pusch_proc_threads);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
389
  if (threadCnt < 2) LOG_E(PHY,"Number of threads for gNB should be more than 1. Allocated only %d\n",threadCnt);
390
  char ul_pool[80];
391
  sprintf(ul_pool,"-1");
392
  int s_offset = 0;
393
  for (int icpu=1; icpu<threadCnt; icpu++) {
394 395
    sprintf(ul_pool+2+s_offset,",-1");
    s_offset += 3;
396
  }
397
  if (getenv("noThreads")) strcpy(ul_pool, "n");
Sakthi's avatar
Sakthi committed
398
  initTpool(ul_pool, gNB->threadPool, false);
399 400
  // ULSCH decoder result FIFO
  gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
Sakthivel Velumani's avatar
Sakthivel Velumani committed
401
  initNotifiedFIFO(gNB->respDecode);
laurent's avatar
laurent committed
402

403
  // L1 RX result FIFO 
Sakthivel Velumani's avatar
Sakthivel Velumani committed
404 405
  gNB->resp_L1 = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
  initNotifiedFIFO(gNB->resp_L1);
406 407
  notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1,rx_func);
  pushNotifiedFIFO(gNB->resp_L1,msg); // to unblock the process in the beginning
Sakthivel Velumani's avatar
Sakthivel Velumani committed
408

409
  // L1 TX result FIFO 
Sakthivel Velumani's avatar
Sakthivel Velumani committed
410 411
  gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
  initNotifiedFIFO(gNB->resp_L1_tx);
412 413 414 415
  // we create 2 threads for L1 tx processing
  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,tx_func);
  processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
  init_DLSCH_struct(gNB, msgDataTx);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
416
  msgDataTx->slot = -1;
417 418 419 420 421 422 423 424
  memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
  reset_meas(&msgDataTx->phy_proc_tx);
  gNB->phy_proc_tx_0 = &msgDataTx->phy_proc_tx;
  pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning

  msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,tx_func);
  msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
  init_DLSCH_struct(gNB, msgDataTx);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
425
  msgDataTx->slot = -1;
426 427 428 429
  memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
  reset_meas(&msgDataTx->phy_proc_tx);
  gNB->phy_proc_tx_1 = &msgDataTx->phy_proc_tx;
  pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
Sakthivel Velumani's avatar
Sakthivel Velumani committed
430

431
  // RU TX result FIFO 
Sakthivel Velumani's avatar
Sakthivel Velumani committed
432 433
  gNB->resp_RU_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
  initNotifiedFIFO(gNB->resp_RU_tx);
434 435
  notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_RU_t),0,gNB->resp_RU_tx,ru_tx_func);
  processingData_RU_t *msgData = (processingData_RU_t*)msgRUTx->msgData;
436 437
  int first_tx_slot = sf_ahead*gNB->frame_parms.slots_per_subframe;
  msgData->next_slot = get_next_downlink_slot(gNB, &gNB->gNB_config, 0, first_tx_slot-1);
438
  pushNotifiedFIFO(gNB->resp_RU_tx,msgRUTx); // to unblock the process in the beginning
439 440

  // Stats measurement thread
441 442 443
  if(opp_enabled == 1) threadCreate(&proc->process_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW);
  threadCreate(&proc->L1_stats_thread,nrL1_stats_thread,(void*)gNB,"L1_stats",-1,OAI_PRIORITY_RT_LOW);

Sakthivel Velumani's avatar
Sakthivel Velumani committed
444
}
laurent's avatar
laurent committed
445 446 447 448 449 450 451 452


/*!
 * \brief Terminate gNB TX and RX threads.
 */
void kill_gNB_proc(int inst) {
  PHY_VARS_gNB *gNB;

453 454 455 456 457
  gNB=RC.gNB[inst];
  
  LOG_I(PHY, "Destroying UL_INFO mutex\n");
  pthread_mutex_destroy(&gNB->UL_INFO_mutex);
  
laurent's avatar
laurent committed
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
}

void reset_opp_meas(void) {
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);

  for (sfn=0; sfn < 10; sfn++) {
    reset_meas(&softmodem_stats_rxtx_sf);
    reset_meas(&softmodem_stats_rx_sf);
  }
}


void print_opp_meas(void) {
  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main gNB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);

  for (sfn=0; sfn < 10; sfn++) {
    print_meas(&softmodem_stats_rxtx_sf,"[gNB][total_phy_proc_rxtx]",NULL, NULL);
    print_meas(&softmodem_stats_rx_sf,"[gNB][total_phy_proc_rx]",NULL,NULL);
  }
}


/// eNB kept in function name for nffapi calls, TO FIX
void init_eNB_afterRU(void) {
486
  int inst,ru_id,i,aa;
laurent's avatar
laurent committed
487 488 489
  PHY_VARS_gNB *gNB;
  LOG_I(PHY,"%s() RC.nb_nr_inst:%d\n", __FUNCTION__, RC.nb_nr_inst);

490 491
  if(NFAPI_MODE == NFAPI_MODE_PNF)
    RC.nb_nr_inst = 1;
laurent's avatar
laurent committed
492
  for (inst=0; inst<RC.nb_nr_inst; inst++) {
493
    LOG_I(PHY,"RC.nb_nr_CC[inst:%d]:%p\n", inst, RC.gNB[inst]);
494 495
    gNB                                  =  RC.gNB[inst];
    phy_init_nr_gNB(gNB,0,0);
496

497 498
    // map antennas and PRACH signals to gNB RX
    if (0) AssertFatal(gNB->num_RU>0,"Number of RU attached to gNB %d is zero\n",gNB->Mod_id);
499

500 501
    LOG_I(PHY,"Mapping RX ports from %d RUs to gNB %d\n",gNB->num_RU,gNB->Mod_id);
    LOG_I(PHY,"gNB->num_RU:%d\n", gNB->num_RU);
502

503 504 505 506 507 508 509 510 511 512
    for (ru_id=0,aa=0; ru_id<gNB->num_RU; ru_id++) {
      AssertFatal(gNB->RU_list[ru_id]->common.rxdataF!=NULL,
		  "RU %d : common.rxdataF is NULL\n",
		  gNB->RU_list[ru_id]->idx);
      AssertFatal(gNB->RU_list[ru_id]->prach_rxsigF!=NULL,
		  "RU %d : prach_rxsigF is NULL\n",
		  gNB->RU_list[ru_id]->idx);
      
      for (i=0; i<gNB->RU_list[ru_id]->nb_rx; aa++,i++) {
	LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n",gNB->RU_list[ru_id]->idx,i,aa);
513
	gNB->prach_vars.rxsigF[aa]    =  gNB->RU_list[ru_id]->prach_rxsigF[0][i];
514 515 516
#if 0
printf("before %p\n", gNB->common_vars.rxdataF[aa]);
#endif
517
	gNB->common_vars.rxdataF[aa]     =  gNB->RU_list[ru_id]->common.rxdataF[i];
518 519 520
#if 0
printf("after %p\n", gNB->common_vars.rxdataF[aa]);
#endif
521
      }
laurent's avatar
laurent committed
522
    }
523

524 525 526 527 528
    /* TODO: review this code, there is something wrong.
     * In monolithic mode, we come here with nb_antennas_rx == 0
     * (not tested in other modes).
     */
    //init_precoding_weights(RC.gNB[inst]);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
529
    init_gNB_Tpool(inst);
laurent's avatar
laurent committed
530 531 532 533 534
  }

}

void init_gNB(int single_thread_flag,int wait_for_sync) {
535

laurent's avatar
laurent committed
536 537 538
  int inst;
  PHY_VARS_gNB *gNB;

Raymond Knopp's avatar
Raymond Knopp committed
539
  if (RC.gNB == NULL) {
540
    RC.gNB = (PHY_VARS_gNB **) calloc(1+RC.nb_nr_L1_inst, sizeof(PHY_VARS_gNB *));
541
    LOG_I(PHY,"gNB L1 structure RC.gNB allocated @ %p\n",RC.gNB);
Raymond Knopp's avatar
Raymond Knopp committed
542
  }
laurent's avatar
laurent committed
543 544

  for (inst=0; inst<RC.nb_nr_L1_inst; inst++) {
Raymond Knopp's avatar
Raymond Knopp committed
545

546
    if (RC.gNB[inst] == NULL) {
547
      RC.gNB[inst] = (PHY_VARS_gNB *) calloc(1, sizeof(PHY_VARS_gNB));
548
      LOG_I(PHY,"[nr-gnb.c] gNB structure RC.gNB[%d] allocated @ %p\n",inst,RC.gNB[inst]);
549
    }
550 551 552 553 554 555 556 557 558
    gNB                     = RC.gNB[inst];
    gNB->abstraction_flag   = 0;
    gNB->single_thread_flag = single_thread_flag;
    /*nr_polar_init(&gNB->nrPolar_params,
      NR_POLAR_PBCH_MESSAGE_TYPE,
      NR_POLAR_PBCH_PAYLOAD_BITS,
      NR_POLAR_PBCH_AGGREGATION_LEVEL);*/
    LOG_I(PHY,"Initializing gNB %d single_thread_flag:%d\n",inst,gNB->single_thread_flag);
    LOG_I(PHY,"Initializing gNB %d\n",inst);
559

560 561 562 563 564 565 566
    LOG_I(PHY,"Registering with MAC interface module (before %p)\n",gNB->if_inst);
    AssertFatal((gNB->if_inst         = NR_IF_Module_init(inst))!=NULL,"Cannot register interface");
    LOG_I(PHY,"Registering with MAC interface module (after %p)\n",gNB->if_inst);
    gNB->if_inst->NR_Schedule_response   = nr_schedule_response;
    gNB->if_inst->NR_PHY_config_req      = nr_phy_config_request;
    memset((void *)&gNB->UL_INFO,0,sizeof(gNB->UL_INFO));
    LOG_I(PHY,"Setting indication lists\n");
567

568 569 570
    gNB->UL_INFO.rx_ind.pdu_list = gNB->rx_pdu_list;
    gNB->UL_INFO.crc_ind.crc_list = gNB->crc_pdu_list;
    /*gNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = gNB->sr_pdu_list;
571 572
    gNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = gNB->harq_pdu_list;
    gNB->UL_INFO.cqi_ind.cqi_pdu_list = gNB->cqi_pdu_list;
573
    gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;*/
574

575
    gNB->prach_energy_counter = 0;
576
    gNB->prb_interpolation = get_softmodem_params()->prb_interpolation;
laurent's avatar
laurent committed
577
  }
578
  
laurent's avatar
laurent committed
579

580
  LOG_I(PHY,"[nr-gnb.c] gNB structure allocated\n");
laurent's avatar
laurent committed
581 582 583 584 585 586 587 588 589
}


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