nr-gnb.c 24.3 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
/*
 * 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
 */

22
/*! \file nr-gnb.c
laurent's avatar
laurent committed
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
 * \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>
41
#include "rt_profiling.h"
laurent's avatar
laurent committed
42 43 44

#include "PHY/types.h"

45
#include "PHY/INIT/nr_phy_init.h"
laurent's avatar
laurent committed
46 47 48 49 50

#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
51
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
52
#include "PHY/MODULATION/nr_modulation.h"
53
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
54
#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h"
laurent's avatar
laurent committed
55 56 57 58

#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

francescomani's avatar
francescomani committed
59
#include "radio/COMMON/common_lib.h"
laurent's avatar
laurent committed
60 61 62 63 64 65 66

//#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/phy_extern.h"

67
#include "common/ran_context.h"
laurent's avatar
laurent committed
68 69 70 71 72 73 74 75 76
#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"
77
#include "gnb_paramdef.h"
laurent's avatar
laurent committed
78

79 80
#include "s1ap_eNB.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"
81
#include <executables/softmodem-common.h>
laurent's avatar
laurent committed
82 83

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

//#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


105
#include "executables/thread-common.h"
laurent's avatar
laurent committed
106 107 108 109


//#define TICK_TO_US(ts) (ts.diff)
#define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials)
110
#define L1STATSSTRLEN 16384
laurent's avatar
laurent committed
111 112


113 114
void tx_func(void *param) 
{
115
  processingData_L1tx_t *info = (processingData_L1tx_t *) param;
116
  PHY_VARS_gNB *gNB = info->gNB;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
117 118
  int frame_tx = info->frame;
  int slot_tx = info->slot;
119
  int cumul_samples = gNB->frame_parms.get_samples_per_slot(0, &gNB->frame_parms);
120 121
  int i = 1;
  for (; i < gNB->frame_parms.slots_per_subframe / 2; i++)
122
    cumul_samples += gNB->frame_parms.get_samples_per_slot(i, &gNB->frame_parms);
123
  int samples = cumul_samples / i;
124 125
  int absslot_tx = info->timestamp_tx / samples;
  int absslot_rx = absslot_tx - gNB->RU_list[0]->sl_ahead;
126
  int rt_prof_idx = absslot_rx % RT_PROF_DEPTH;
127
  start_meas(&gNB->phy_proc_tx);
128

129
  clock_gettime(CLOCK_MONOTONIC, &gNB->rt_L1_profiling.start_L1_TX[rt_prof_idx]);
130 131 132 133
  phy_procedures_gNB_TX(info,
                        frame_tx,
                        slot_tx,
                        1);
134
  clock_gettime(CLOCK_MONOTONIC, &gNB->rt_L1_profiling.return_L1_TX[rt_prof_idx]);
135

136 137 138 139 140 141 142 143 144
  if (get_softmodem_params()->reorder_thread_disable) {
    processingData_RU_t syncMsgRU;
    syncMsgRU.frame_tx = frame_tx;
    syncMsgRU.slot_tx = slot_tx;
    syncMsgRU.ru = gNB->RU_list[0];
    syncMsgRU.timestamp_tx = info->timestamp_tx;
    LOG_D(PHY,"gNB: %d.%d : calling RU TX function\n",syncMsgRU.frame_tx,syncMsgRU.slot_tx);
    ru_tx_func((void*)&syncMsgRU);
  }
145 146
  /* this thread is done with the sched_info, decrease the reference counter */
  deref_sched_response(info->sched_response_id);
147
  stop_meas(&gNB->phy_proc_tx);
148 149 150
}


151 152
void *L1_rx_thread(void *arg) 
{
153 154 155 156
  PHY_VARS_gNB *gNB = (PHY_VARS_gNB*)arg;

  while (oai_exit == 0) {
     notifiedFIFO_elt_t *res = pullNotifiedFIFO(&gNB->resp_L1);
157 158
     if (res == NULL)
       break;
159 160 161 162 163
     processingData_L1_t *info = (processingData_L1_t *)NotifiedFifoData(res);
     rx_func(info);
     delNotifiedFIFO_elt(res);
  }
  return NULL;
164
}
165
/* to be added for URLLC, requires MAC scheduling to be split from UL indication 
166 167 168 169 170 171 172 173 174 175 176
void *L1_tx_thread(void *arg) {
  PHY_VARS_gNB *gNB = (PHY_VARS_gNB*)arg;

  while (oai_exit == 0) {
     notifiedFIFO_elt_t *res = pullNotifiedFIFO(&gNB->L1_tx_out);
     processingData_L1tx_t *info = (processingData_L1tx_t *)NotifiedFifoData(res);
     tx_func(info);
     delNotifiedFIFO_elt(res);
  }
  return NULL;
}
177
*/
178 179
void rx_func(void *param)
{
180 181 182 183 184 185
  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;
186
  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
187
  int cumul_samples = gNB->frame_parms.get_samples_per_slot(0, &gNB->frame_parms);
188 189
  int i = 1;
  for (; i < gNB->frame_parms.slots_per_subframe / 2; i++)
190
    cumul_samples += gNB->frame_parms.get_samples_per_slot(i, &gNB->frame_parms);
191
  int samples = cumul_samples / i;
192
  int absslot_tx = info->timestamp_tx / samples;
193 194 195
  int absslot_rx = absslot_tx - gNB->RU_list[0]->sl_ahead;
  int rt_prof_idx = absslot_rx % RT_PROF_DEPTH;
  clock_gettime(CLOCK_MONOTONIC,&info->gNB->rt_L1_profiling.start_L1_RX[rt_prof_idx]);
laurent's avatar
laurent committed
196 197 198
  start_meas(&softmodem_stats_rxtx_sf);

  // *******************************************************************
199

200
  if (NFAPI_MODE == NFAPI_MODE_PNF) {
laurent's avatar
laurent committed
201
    // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick
202
    //LOG_D(PHY, "oai_nfapi_slot_ind(frame:%u, slot:%d) ********\n", frame_rx, slot_rx);
laurent's avatar
laurent committed
203
    start_meas(&nfapi_meas);
204
    handle_nr_slot_ind(frame_rx, slot_rx);
laurent's avatar
laurent committed
205 206 207 208
    stop_meas(&nfapi_meas);

  }
  // ****************************************
209

210
  T(T_GNB_PHY_DL_TICK, T_INT(gNB->Mod_id), T_INT(frame_tx), T_INT(slot_tx));
211

francescomani's avatar
francescomani committed
212 213
  reset_active_stats(gNB, frame_tx);
  reset_active_ulsch(gNB, frame_tx);
214

215
  // RX processing
francescomani's avatar
francescomani committed
216
  int rx_slot_type = nr_slot_select(cfg, frame_rx, slot_rx);
217 218 219
  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
220 221

    // Do PRACH RU processing
222
    L1_nr_prach_procedures(gNB,frame_rx,slot_rx);
223

224
    //WA: comment rotation in tx/rx
225
    if (gNB->phase_comp) {
226
      //apply the rx signal rotation here
227
      int soffset = (slot_rx & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size;
228
      for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) {
229 230 231 232 233 234 235 236
        apply_nr_rotation_RX(&gNB->frame_parms,
                             gNB->common_vars.rxdataF[aa],
                             gNB->frame_parms.symbol_rotation[1],
                             slot_rx,
                             gNB->frame_parms.N_RB_UL,
                             soffset,
                             0,
                             gNB->frame_parms.Ncp == EXTENDED ? 12 : 14);
237
      }
238
    }
239 240 241
    phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
  }

242
  stop_meas( &softmodem_stats_rxtx_sf );
243
  LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx);
244
  clock_gettime(CLOCK_MONOTONIC,&info->gNB->rt_L1_profiling.return_L1_RX[rt_prof_idx]);
laurent's avatar
laurent committed
245

246 247
  // Call the scheduler
  start_meas(&gNB->ul_indication_stats);
248
//  pthread_mutex_lock(&gNB->UL_INFO_mutex);
249 250 251 252 253
  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);
254
//  pthread_mutex_unlock(&gNB->UL_INFO_mutex);
255
  stop_meas(&gNB->ul_indication_stats);
256

257
  int tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx);
258
  if ((tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) && NFAPI_MODE != NFAPI_MODE_PNF) {
259
    notifiedFIFO_elt_t *res;
260 261 262
    processingData_L1tx_t *syncMsg;
    // Its a FIFO so it maitains the order in which the MAC fills the messages
    // so no need for checking for right slot
263 264 265 266 267 268 269
    if (get_softmodem_params()->reorder_thread_disable) {
      // call the TX function directly from this thread
      syncMsg = gNB->msgDataTx;
      syncMsg->gNB = gNB; 
      syncMsg->timestamp_tx = info->timestamp_tx;
      tx_func(syncMsg);
    } else {
270
      res = pullTpool(&gNB->L1_tx_filled, &gNB->threadPool);
271 272 273 274 275 276 277 278
      if (res == NULL)
        return; // Tpool has been stopped
      syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
      syncMsg->gNB = gNB;
      syncMsg->timestamp_tx = info->timestamp_tx;
      res->key = slot_tx;
      pushTpool(&gNB->threadPool, res);
    }
279
  } else if (get_softmodem_params()->continuous_tx) {
280
    notifiedFIFO_elt_t *res = pullNotifiedFIFO(&gNB->L1_tx_free);
281 282
    if (res == NULL)
      return; // Tpool has been stopped
283 284 285 286 287 288
    processingData_L1tx_t *syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
    syncMsg->gNB = gNB;
    syncMsg->timestamp_tx = info->timestamp_tx;
    syncMsg->frame = frame_tx;
    syncMsg->slot = slot_tx;
    res->key = slot_tx;
289
    pushNotifiedFIFO(&gNB->L1_tx_out, res);
laurent's avatar
laurent committed
290
  }
291

laurent's avatar
laurent committed
292
}
293 294 295 296 297
static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size_t outputlen) {
  const char *begin = output;
  const char *end = output + outputlen;
  output += print_meas_log(&gNB->phy_proc_tx, "L1 Tx processing", NULL, NULL, output, end - output);
  output += print_meas_log(&gNB->dlsch_encoding_stats, "DLSCH encoding", NULL, NULL, output, end - output);
298 299 300 301 302
  output += print_meas_log(&gNB->dlsch_scrambling_stats, "DLSCH scrambling", NULL, NULL, output, end-output);
  output += print_meas_log(&gNB->dlsch_modulation_stats, "DLSCH modulation", NULL, NULL, output, end-output);
  output += print_meas_log(&gNB->dlsch_layer_mapping_stats, "DLSCH layer mapping", NULL, NULL, output,end-output);
  output += print_meas_log(&gNB->dlsch_resource_mapping_stats, "DLSCH resource mapping", NULL, NULL, output,end-output);
  output += print_meas_log(&gNB->dlsch_precoding_stats, "DLSCH precoding", NULL, NULL, output,end-output);
303 304 305 306 307
  output += print_meas_log(&gNB->phy_proc_rx, "L1 Rx processing", NULL, NULL, output, end - output);
  output += print_meas_log(&gNB->ul_indication_stats, "UL Indication", NULL, NULL, output, end - output);
  output += print_meas_log(&gNB->rx_pusch_stats, "PUSCH inner-receiver", NULL, NULL, output, end - output);
  output += print_meas_log(&gNB->ulsch_decoding_stats, "PUSCH decoding", NULL, NULL, output, end - output);
  output += print_meas_log(&gNB->schedule_response_stats, "Schedule Response", NULL, NULL, output, end - output);
Robert Schmidt's avatar
Robert Schmidt committed
308
  output += print_meas_log(&gNB->rx_prach, "PRACH RX", NULL, NULL, output, end - output);
309 310
  if (ru->feprx)
    output += print_meas_log(&ru->ofdm_demod_stats, "feprx", NULL, NULL, output, end - output);
311

312
  if (ru->feptx_prec) {
313
    output += print_meas_log(&ru->precoding_stats,"feptx_prec",NULL,NULL, output, end - output);
314 315 316
  }

  if (ru->feptx_ofdm) {
317 318 319
    output += print_meas_log(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL, output, end - output);
    output += print_meas_log(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL, output, end - output);
    output += print_meas_log(&ru->ofdm_total_stats,"feptx_total",NULL,NULL, output, end - output);
320
  }
321

322 323
  if (ru->fh_north_asynch_in)
    output += print_meas_log(&ru->rx_fhaul,"rx_fhaul",NULL,NULL, output, end - output);
324

325
  output += print_meas_log(&ru->tx_fhaul,"tx_fhaul",NULL,NULL, output, end - output);
326

327
  if (ru->fh_north_out) {
328 329
    output += print_meas_log(&ru->compression,"compression",NULL,NULL, output, end - output);
    output += print_meas_log(&ru->transport,"transport",NULL,NULL, output, end - output);
330
  }
331
  return output - begin;
332 333
}

334 335
void *nrL1_stats_thread(void *param) {
  PHY_VARS_gNB     *gNB      = (PHY_VARS_gNB *)param;
336 337 338
  RU_t *ru = RC.ru[0];
  char output[L1STATSSTRLEN];
  memset(output,0,L1STATSSTRLEN);
339 340
  wait_sync("L1_stats_thread");
  FILE *fd;
341 342 343
  fd=fopen("nrL1_stats.log","w");
  AssertFatal(fd!=NULL,"Cannot open nrL1_stats.log\n");

344
  reset_meas(&gNB->phy_proc_tx);
345 346 347 348 349
  reset_meas(&gNB->dlsch_encoding_stats);
  reset_meas(&gNB->phy_proc_rx);
  reset_meas(&gNB->ul_indication_stats);
  reset_meas(&gNB->rx_pusch_stats);
  reset_meas(&gNB->ulsch_decoding_stats);
350
  reset_meas(&gNB->schedule_response_stats);
351 352 353 354 355
  reset_meas(&gNB->dlsch_scrambling_stats);
  reset_meas(&gNB->dlsch_modulation_stats);
  reset_meas(&gNB->dlsch_layer_mapping_stats);
  reset_meas(&gNB->dlsch_resource_mapping_stats);
  reset_meas(&gNB->dlsch_precoding_stats);
356 357 358
  while (!oai_exit) {
    sleep(1);
    dump_nr_I0_stats(fd,gNB);
359
    dump_pdsch_stats(fd,gNB);
360
    dump_pusch_stats(fd,gNB);
361
    dump_L1_meas_stats(gNB, ru, output, L1STATSSTRLEN);
362 363 364
    fprintf(fd,"%s\n",output);
    fflush(fd);
    fseek(fd,0,SEEK_SET);
365
  }
366
  fclose(fd);
367 368 369
  return(NULL);
}

370 371 372 373 374
// This thread reads the finished L1 tx jobs from threaPool
// and pushes RU tx thread in the right order. It works only
// two parallel L1 tx threads.
void *tx_reorder_thread(void* param) {
  PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
375
  
376
  notifiedFIFO_elt_t *resL1Reserve = pullNotifiedFIFO(&gNB->L1_tx_out);
377
  AssertFatal(resL1Reserve != NULL, "pullTpool() did not return start message in %s\n", __func__);
378 379
  int next_tx_slot=((processingData_L1tx_t *)NotifiedFifoData(resL1Reserve))->slot;
  
380 381
  LOG_I(PHY,"tx_reorder_thread started\n");
  
382
  while (!oai_exit) {
383
    notifiedFIFO_elt_t *resL1;
384
    if (resL1Reserve) {
385 386
       resL1=resL1Reserve;
       if (((processingData_L1tx_t *)NotifiedFifoData(resL1))->slot != next_tx_slot) {
387
         LOG_E(PHY,"order mistake\n");
388
         resL1Reserve = NULL;
389
         resL1 = pullNotifiedFIFO(&gNB->L1_tx_out);
390
       }
391 392
     } else {
       resL1 = pullNotifiedFIFO(&gNB->L1_tx_out);
393
       if (resL1 != NULL && ((processingData_L1tx_t *)NotifiedFifoData(resL1))->slot != next_tx_slot) {
394 395
          if (resL1Reserve)
              LOG_E(PHY,"error, have a stored packet, then a second one\n");
396
          resL1Reserve = resL1;
397
          resL1 = pullNotifiedFIFO(&gNB->L1_tx_out);
398
          if (((processingData_L1tx_t *)NotifiedFifoData(resL1))->slot != next_tx_slot)
399
            LOG_E(PHY,"error, pull two msg, none is good\n");
400
       }
401
    }
402 403
    if (resL1 == NULL)
      break; // Tpool has been stopped
404 405 406 407 408 409
    processingData_L1tx_t *syncMsgL1= (processingData_L1tx_t *)NotifiedFifoData(resL1);
    processingData_RU_t syncMsgRU;
    syncMsgRU.frame_tx = syncMsgL1->frame;
    syncMsgRU.slot_tx = syncMsgL1->slot;
    syncMsgRU.timestamp_tx = syncMsgL1->timestamp_tx;
    syncMsgRU.ru = gNB->RU_list[0];
410 411 412 413 414
    if (get_softmodem_params()->continuous_tx) {
      int slots_per_frame = gNB->frame_parms.slots_per_frame;
      next_tx_slot = (syncMsgRU.slot_tx + 1) % slots_per_frame;
    } else
      next_tx_slot = get_next_downlink_slot(gNB, &gNB->gNB_config, syncMsgRU.frame_tx, syncMsgRU.slot_tx);
415
    pushNotifiedFIFO(&gNB->L1_tx_free, resL1);
416 417
    if (resL1==resL1Reserve)
       resL1Reserve=NULL;
418
    LOG_D(PHY,"gNB: %d.%d : calling RU TX function\n",syncMsgL1->frame,syncMsgL1->slot);
419
    ru_tx_func((void*)&syncMsgRU);
420 421 422 423
  }
  return(NULL);
}

Sakthivel Velumani's avatar
Sakthivel Velumani committed
424
void init_gNB_Tpool(int inst) {
laurent's avatar
laurent committed
425
  PHY_VARS_gNB *gNB;
426
  gNB = RC.gNB[inst];
427
  gNB_L1_proc_t *proc = &gNB->proc;
Tsung-Yu Chan's avatar
Tsung-Yu Chan committed
428 429
  // PUSCH symbols per thread need to be calculated by how many threads we have
  gNB->num_pusch_symbols_per_thread = 1;
430 431
  // ULSCH decoding threadpool
  initTpool(get_softmodem_params()->threadPoolConfig, &gNB->threadPool, cpumeas(CPUMEAS_GETSTATE));
432
  // ULSCH decoder result FIFO
433
  initNotifiedFIFO(&gNB->respPuschSymb);
434
  initNotifiedFIFO(&gNB->respDecode);
laurent's avatar
laurent committed
435

436
  // L1 RX result FIFO 
437
  initNotifiedFIFO(&gNB->resp_L1);
438 439 440 441
  if (!get_softmodem_params()->reorder_thread_disable) {
    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
  }
442
  // L1 TX result FIFO 
443 444 445
  initNotifiedFIFO(&gNB->L1_tx_free);
  initNotifiedFIFO(&gNB->L1_tx_filled);
  initNotifiedFIFO(&gNB->L1_tx_out);
446 447
 
  if (get_softmodem_params()->reorder_thread_disable) {
448 449 450 451 452 453 454
    // create the RX thread responsible for triggering RX processing and then TX processing if a single thread is used	  
    threadCreate(&gNB->L1_rx_thread, L1_rx_thread, (void *)gNB, "L1_rx_thread",
                 gNB->L1_rx_thread_core, OAI_PRIORITY_RT_MAX);
    // if separate threads are used for RX and TX, create the TX thread
 // threadCreate(&gNB->L1_tx_thread, L1_tx_thread, (void *)gNB, "L1_tx_thread",
 //              gNB->L1_tx_thread_core, OAI_PRIORITY_RT_MAX);

455
    notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, tx_func);
Laurent THOMAS's avatar
Laurent THOMAS committed
456
    processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
457
    memset(msgDataTx, 0, sizeof(processingData_L1tx_t));
Laurent THOMAS's avatar
Laurent THOMAS committed
458 459
    init_DLSCH_struct(gNB, msgDataTx);
    memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
460
    // this will be removed when the msgDataTx is not necessary anymore
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
    gNB->msgDataTx = msgDataTx;
  } else {
    // we create 2 threads for L1 tx processing
    for (int i=0; i < 2; i++) {
      notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, tx_func);
      processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
      memset(msgDataTx, 0, sizeof(processingData_L1tx_t));
      init_DLSCH_struct(gNB, msgDataTx);
      memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
      pushNotifiedFIFO(&gNB->L1_tx_free, msgL1Tx); // to unblock the process in the beginning
    }
  
    LOG_I(PHY,"Creating thread for TX reordering and dispatching to RU\n");
    threadCreate(&proc->pthread_tx_reorder, tx_reorder_thread, (void *)gNB, "thread_tx_reorder",
                  gNB->RU_list[0] ? gNB->RU_list[0]->tpcores[1] : -1, OAI_PRIORITY_RT_MAX);
Laurent THOMAS's avatar
Laurent THOMAS committed
476
  }
Sakthivel Velumani's avatar
Sakthivel Velumani committed
477

478
  if ((!get_softmodem_params()->emulate_l1) && (!IS_SOFTMODEM_NOSTATS_BIT) && (NFAPI_MODE!=NFAPI_MODE_VNF))
Laurent THOMAS's avatar
Laurent THOMAS committed
479 480
     threadCreate(&proc->L1_stats_thread,nrL1_stats_thread,(void*)gNB,"L1_stats",-1,OAI_PRIORITY_RT_LOW);

Sakthivel Velumani's avatar
Sakthivel Velumani committed
481
}
laurent's avatar
laurent committed
482 483


Robert Schmidt's avatar
Robert Schmidt committed
484 485 486
void term_gNB_Tpool(int inst) {
  PHY_VARS_gNB *gNB = RC.gNB[inst];
  abortTpool(&gNB->threadPool);
487 488 489 490 491
  abortNotifiedFIFO(&gNB->respDecode);
  abortNotifiedFIFO(&gNB->resp_L1);
  abortNotifiedFIFO(&gNB->L1_tx_free);
  abortNotifiedFIFO(&gNB->L1_tx_filled);
  abortNotifiedFIFO(&gNB->L1_tx_out);
492 493 494 495

  gNB_L1_proc_t *proc = &gNB->proc;
  if (!get_softmodem_params()->emulate_l1)
    pthread_join(proc->L1_stats_thread, NULL);
496 497
  if (!get_softmodem_params()->reorder_thread_disable)
    pthread_join(proc->pthread_tx_reorder, NULL);
Robert Schmidt's avatar
Robert Schmidt committed
498 499
}

laurent's avatar
laurent committed
500 501 502 503 504 505
/*!
 * \brief Terminate gNB TX and RX threads.
 */
void kill_gNB_proc(int inst) {
  PHY_VARS_gNB *gNB;

506 507 508 509 510
  gNB=RC.gNB[inst];
  
  LOG_I(PHY, "Destroying UL_INFO mutex\n");
  pthread_mutex_destroy(&gNB->UL_INFO_mutex);
  
laurent's avatar
laurent committed
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
}

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) {
539
  int inst,ru_id,i,aa;
laurent's avatar
laurent committed
540 541 542
  PHY_VARS_gNB *gNB;
  LOG_I(PHY,"%s() RC.nb_nr_inst:%d\n", __FUNCTION__, RC.nb_nr_inst);

543 544
  if(NFAPI_MODE == NFAPI_MODE_PNF)
    RC.nb_nr_inst = 1;
laurent's avatar
laurent committed
545
  for (inst=0; inst<RC.nb_nr_inst; inst++) {
546
    LOG_I(PHY,"RC.nb_nr_CC[inst:%d]:%p\n", inst, RC.gNB[inst]);
547

548
    gNB = RC.gNB[inst];
549
    gNB->ldpc_offload_flag = get_softmodem_params()->ldpc_offload_flag;
550
    gNB->reorder_thread_disable = get_softmodem_params()->reorder_thread_disable;
551

552
    phy_init_nr_gNB(gNB);
553

554 555
    // 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);
556

557 558
    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);
559

560 561 562 563 564 565 566 567 568
    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++) {
569 570
        LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n",gNB->RU_list[ru_id]->idx,i,aa);
        gNB->prach_vars.rxsigF[aa]    =  gNB->RU_list[ru_id]->prach_rxsigF[0][i];
571
        gNB->common_vars.rxdataF[aa]     =  (c16_t *)gNB->RU_list[ru_id]->common.rxdataF[i];
572
      }
laurent's avatar
laurent committed
573
    }
574

575 576 577 578 579
    /* 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
580
    init_gNB_Tpool(inst);
laurent's avatar
laurent committed
581 582 583 584 585
  }

}

void init_gNB(int single_thread_flag,int wait_for_sync) {
586

laurent's avatar
laurent committed
587 588 589
  int inst;
  PHY_VARS_gNB *gNB;

Raymond Knopp's avatar
Raymond Knopp committed
590
  if (RC.gNB == NULL) {
591
    RC.gNB = (PHY_VARS_gNB **) calloc(1+RC.nb_nr_L1_inst, sizeof(PHY_VARS_gNB *));
592
    LOG_I(PHY,"gNB L1 structure RC.gNB allocated @ %p\n",RC.gNB);
Raymond Knopp's avatar
Raymond Knopp committed
593
  }
laurent's avatar
laurent committed
594 595

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

597
    if (RC.gNB[inst] == NULL) {
598
      RC.gNB[inst] = (PHY_VARS_gNB *) calloc(1, sizeof(PHY_VARS_gNB));
599
      LOG_I(PHY,"[nr-gnb.c] gNB structure RC.gNB[%d] allocated @ %p\n",inst,RC.gNB[inst]);
600
    }
601 602 603 604 605 606 607 608 609
    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);
610

611 612 613 614 615 616 617
    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");
618

619 620 621
    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;
622 623
    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;
624
    gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;*/
625

626
    gNB->prach_energy_counter = 0;
627 628
    gNB->chest_time = get_softmodem_params()->chest_time;
    gNB->chest_freq = get_softmodem_params()->chest_freq;
629

laurent's avatar
laurent committed
630
  }
631
  
laurent's avatar
laurent committed
632

633
  LOG_I(PHY,"[nr-gnb.c] gNB structure allocated\n");
laurent's avatar
laurent committed
634 635 636 637 638 639
}


void stop_gNB(int nb_inst) {
  for (int inst=0; inst<nb_inst; inst++) {
    LOG_I(PHY,"Killing gNB %d processing threads\n",inst);
Robert Schmidt's avatar
Robert Schmidt committed
640
    term_gNB_Tpool(inst);
laurent's avatar
laurent committed
641 642 643
    kill_gNB_proc(inst);
  }
}