nr-gnb.c 20.7 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"
55 56
#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
laurent's avatar
laurent committed
57 58 59 60

#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
61
#include "radio/COMMON/common_lib.h"
laurent's avatar
laurent committed
62 63 64 65 66 67 68

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

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

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

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

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


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


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

114
static void tx_func(void *param)
115
{
116
  processingData_L1tx_t *info = (processingData_L1tx_t *) param;
117

Sakthivel Velumani's avatar
Sakthivel Velumani committed
118 119
  int frame_tx = info->frame;
  int slot_tx = info->slot;
120 121 122 123 124 125 126 127 128 129 130
  int frame_rx = info->frame_rx;
  int slot_rx = info->slot_rx;
  int absslot_tx = info->timestamp_tx / info->gNB->frame_parms.get_samples_per_slot(slot_tx, &info->gNB->frame_parms);
  int absslot_rx = absslot_tx - info->gNB->RU_list[0]->sl_ahead;

  LOG_D(NR_PHY, "%d.%d running tx_func\n", frame_tx, slot_tx);
  PHY_VARS_gNB *gNB = info->gNB;
  module_id_t module_id = gNB->Mod_id;
  uint8_t CC_id = gNB->CC_id;
  NR_IF_Module_t *ifi = gNB->if_inst;
  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
131

132
  T(T_GNB_PHY_DL_TICK, T_INT(gNB->Mod_id), T_INT(frame_tx), T_INT(slot_tx));
133

134 135 136 137 138
  if (slot_rx == 0) {
    reset_active_stats(gNB, frame_rx);
    reset_active_ulsch(gNB, frame_rx);
  }

139
  start_meas(&gNB->slot_indication_stats);
140
  ifi->NR_slot_indication(module_id, CC_id, frame_tx, slot_tx);
141
  stop_meas(&gNB->slot_indication_stats);
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
  gNB->msgDataTx->timestamp_tx = info->timestamp_tx;
  info = gNB->msgDataTx;
  info->gNB = gNB;

  // At this point, MAC scheduler just ran, including scheduling
  // PRACH/PUCCH/PUSCH, so trigger RX chain processing
  LOG_D(NR_PHY, "%s() trigger RX for %d.%d\n", __func__, frame_rx, slot_rx);
  notifiedFIFO_elt_t *res = newNotifiedFIFO_elt(sizeof(processingData_L1_t), 0, &gNB->resp_L1, NULL);
  processingData_L1_t *syncMsg = NotifiedFifoData(res);
  syncMsg->gNB = gNB;
  syncMsg->frame_rx = frame_rx;
  syncMsg->slot_rx = slot_rx;
  syncMsg->timestamp_tx = info->timestamp_tx;
  res->key = slot_rx;
  pushNotifiedFIFO(&gNB->resp_L1, res);

  int tx_slot_type = nr_slot_select(cfg, frame_tx, slot_tx);
  if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx) {
    start_meas(&info->gNB->phy_proc_tx);
    phy_procedures_gNB_TX(info, frame_tx, slot_tx, 1);
    const int rt_prof_idx = absslot_rx % RT_PROF_DEPTH;
    clock_gettime(CLOCK_MONOTONIC, &info->gNB->rt_L1_profiling.return_L1_TX[rt_prof_idx]);

    PHY_VARS_gNB *gNB = info->gNB;
166 167 168 169 170
    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;
171 172 173
    LOG_D(PHY, "gNB: %d.%d : calling RU TX function\n", syncMsgRU.frame_tx, syncMsgRU.slot_tx);
    ru_tx_func((void *)&syncMsgRU);
    stop_meas(&info->gNB->phy_proc_tx);
174
  }
175
  /* this thread is done with the sched_info, decrease the reference counter */
176
  LOG_D(NR_PHY, "Calling deref_sched_response for id %d (tx_func) in %d.%d\n", info->sched_response_id, frame_tx, slot_tx);
177
  deref_sched_response(info->sched_response_id);
178 179 180
}


181 182
void *L1_rx_thread(void *arg) 
{
183 184 185 186
  PHY_VARS_gNB *gNB = (PHY_VARS_gNB*)arg;

  while (oai_exit == 0) {
     notifiedFIFO_elt_t *res = pullNotifiedFIFO(&gNB->resp_L1);
187 188
     if (res == NULL)
       break;
189 190 191 192 193
     processingData_L1_t *info = (processingData_L1_t *)NotifiedFifoData(res);
     rx_func(info);
     delNotifiedFIFO_elt(res);
  }
  return NULL;
194
}
195
// Added for URLLC, requires MAC scheduling to be split from UL indication
196 197 198 199 200
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);
201 202
     if (res == NULL) // stopping condition, happens only when queue is freed
       break;
203 204 205 206 207 208
     processingData_L1tx_t *info = (processingData_L1tx_t *)NotifiedFifoData(res);
     tx_func(info);
     delNotifiedFIFO_elt(res);
  }
  return NULL;
}
209

210 211
void rx_func(void *param)
{
212 213 214 215
  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;
216
  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
217
  int cumul_samples = gNB->frame_parms.get_samples_per_slot(0, &gNB->frame_parms);
218 219
  int i = 1;
  for (; i < gNB->frame_parms.slots_per_subframe / 2; i++)
220
    cumul_samples += gNB->frame_parms.get_samples_per_slot(i, &gNB->frame_parms);
221
  int samples = cumul_samples / i;
222
  int absslot_tx = info->timestamp_tx / samples;
223 224 225
  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
226 227 228
  start_meas(&softmodem_stats_rxtx_sf);

  // *******************************************************************
229

230
  if (NFAPI_MODE == NFAPI_MODE_PNF) {
laurent's avatar
laurent committed
231
    // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick
232
    //LOG_D(PHY, "oai_nfapi_slot_ind(frame:%u, slot:%d) ********\n", frame_rx, slot_rx);
laurent's avatar
laurent committed
233
    start_meas(&nfapi_meas);
234
    handle_nr_slot_ind(frame_rx, slot_rx);
laurent's avatar
laurent committed
235 236 237 238
    stop_meas(&nfapi_meas);

  }
  // ****************************************
239 240

  // RX processing
francescomani's avatar
francescomani committed
241
  int rx_slot_type = nr_slot_select(cfg, frame_rx, slot_rx);
242
  if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) {
243 244
    LOG_D(NR_PHY, "%d.%d Starting RX processing\n", frame_rx, slot_rx);

245 246
    // UE-specific RX processing for subframe n
    // TODO: check if this is correct for PARALLEL_RU_L1_TRX_SPLIT
247 248

    // Do PRACH RU processing
249
    L1_nr_prach_procedures(gNB,frame_rx,slot_rx);
250

251
    //WA: comment rotation in tx/rx
252
    if (gNB->phase_comp) {
253
      //apply the rx signal rotation here
254
      int soffset = (slot_rx & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size;
255
      for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) {
256 257 258 259 260 261 262 263
        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);
264
      }
265
    }
266 267
    phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);

268 269 270 271 272 273 274 275 276 277 278
    // Call the scheduler
    start_meas(&gNB->ul_indication_stats);
    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);
    stop_meas(&gNB->ul_indication_stats);

    notifiedFIFO_elt_t *res = newNotifiedFIFO_elt(sizeof(processingData_L1_t), 0, &gNB->L1_rx_out, NULL);
    processingData_L1_t *syncMsg = NotifiedFifoData(res);
279
    syncMsg->gNB = gNB;
280 281 282 283 284
    syncMsg->frame_rx = frame_rx;
    syncMsg->slot_rx = slot_rx;
    res->key = slot_rx;
    LOG_D(NR_PHY, "Signaling completion for %d.%d (mod_slot %d) on L1_rx_out\n", frame_rx, slot_rx, slot_rx % RU_RX_SLOT_DEPTH);
    pushNotifiedFIFO(&gNB->L1_rx_out, res);
laurent's avatar
laurent committed
285
  }
286

287 288
  stop_meas(&softmodem_stats_rxtx_sf);
  clock_gettime(CLOCK_MONOTONIC, &info->gNB->rt_L1_profiling.return_L1_RX[rt_prof_idx]);
laurent's avatar
laurent committed
289
}
290

291 292 293 294 295
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);
296 297 298 299 300
  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);
301 302
  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);
303
  output += print_meas_log(&gNB->slot_indication_stats, "Slot Indication", NULL, NULL, output, end - output);
304 305
  output += print_meas_log(&gNB->rx_pusch_stats, "PUSCH inner-receiver", 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
306
  output += print_meas_log(&gNB->rx_prach, "PRACH RX", NULL, NULL, output, end - output);
307 308
  if (ru->feprx)
    output += print_meas_log(&ru->ofdm_demod_stats, "feprx", NULL, NULL, output, end - output);
309

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

  if (ru->feptx_ofdm) {
315 316 317
    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);
318
  }
319

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

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

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

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

342
  reset_meas(&gNB->phy_proc_tx);
343 344 345
  reset_meas(&gNB->dlsch_encoding_stats);
  reset_meas(&gNB->phy_proc_rx);
  reset_meas(&gNB->ul_indication_stats);
346
  reset_meas(&gNB->slot_indication_stats);
347
  reset_meas(&gNB->rx_pusch_stats);
348
  reset_meas(&gNB->schedule_response_stats);
349 350 351 352 353
  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);
354 355 356
  while (!oai_exit) {
    sleep(1);
    dump_nr_I0_stats(fd,gNB);
357
    dump_pdsch_stats(fd,gNB);
358
    dump_pusch_stats(fd,gNB);
359
    dump_L1_meas_stats(gNB, ru, output, L1STATSSTRLEN);
360 361 362
    fprintf(fd,"%s\n",output);
    fflush(fd);
    fseek(fd,0,SEEK_SET);
363
  }
364
  fclose(fd);
365 366 367
  return(NULL);
}

Sakthivel Velumani's avatar
Sakthivel Velumani committed
368
void init_gNB_Tpool(int inst) {
laurent's avatar
laurent committed
369
  PHY_VARS_gNB *gNB;
370
  gNB = RC.gNB[inst];
371
  gNB_L1_proc_t *proc = &gNB->proc;
Tsung-Yu Chan's avatar
Tsung-Yu Chan committed
372 373
  // PUSCH symbols per thread need to be calculated by how many threads we have
  gNB->num_pusch_symbols_per_thread = 1;
374 375
  // ULSCH decoding threadpool
  initTpool(get_softmodem_params()->threadPoolConfig, &gNB->threadPool, cpumeas(CPUMEAS_GETSTATE));
376
  // ULSCH decoder result FIFO
377
  initNotifiedFIFO(&gNB->respPuschSymb);
378
  initNotifiedFIFO(&gNB->respDecode);
laurent's avatar
laurent committed
379

380
  // L1 RX result FIFO
381
  initNotifiedFIFO(&gNB->resp_L1);
382
  // L1 TX result FIFO 
383 384 385
  initNotifiedFIFO(&gNB->L1_tx_free);
  initNotifiedFIFO(&gNB->L1_tx_filled);
  initNotifiedFIFO(&gNB->L1_tx_out);
386 387 388 389 390 391 392 393 394 395 396 397 398 399
  initNotifiedFIFO(&gNB->L1_rx_out);

  // create the RX thread responsible for RX processing start event (resp_L1 msg queue), then launch rx_func()
  threadCreate(&gNB->L1_rx_thread, L1_rx_thread, (void *)gNB, "L1_rx_thread", gNB->L1_rx_thread_core, OAI_PRIORITY_RT_MAX);
  // create the TX thread responsible for TX processing start event (L1_tx_out msg queue), then launch tx_func()
  threadCreate(&gNB->L1_tx_thread, L1_tx_thread, (void *)gNB, "L1_tx_thread", gNB->L1_tx_thread_core, OAI_PRIORITY_RT_MAX);

  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));
  // this will be removed when the msgDataTx is not necessary anymore
  gNB->msgDataTx = msgDataTx;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
400

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

Sakthivel Velumani's avatar
Sakthivel Velumani committed
404
}
laurent's avatar
laurent committed
405 406


Robert Schmidt's avatar
Robert Schmidt committed
407 408 409
void term_gNB_Tpool(int inst) {
  PHY_VARS_gNB *gNB = RC.gNB[inst];
  abortTpool(&gNB->threadPool);
410 411 412 413 414
  abortNotifiedFIFO(&gNB->respDecode);
  abortNotifiedFIFO(&gNB->resp_L1);
  abortNotifiedFIFO(&gNB->L1_tx_free);
  abortNotifiedFIFO(&gNB->L1_tx_filled);
  abortNotifiedFIFO(&gNB->L1_tx_out);
415
  abortNotifiedFIFO(&gNB->L1_rx_out);
416 417 418 419

  gNB_L1_proc_t *proc = &gNB->proc;
  if (!get_softmodem_params()->emulate_l1)
    pthread_join(proc->L1_stats_thread, NULL);
Robert Schmidt's avatar
Robert Schmidt committed
420 421
}

laurent's avatar
laurent committed
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
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) {
448
  int inst,ru_id,i,aa;
laurent's avatar
laurent committed
449 450 451
  PHY_VARS_gNB *gNB;
  LOG_I(PHY,"%s() RC.nb_nr_inst:%d\n", __FUNCTION__, RC.nb_nr_inst);

452 453
  if(NFAPI_MODE == NFAPI_MODE_PNF)
    RC.nb_nr_inst = 1;
laurent's avatar
laurent committed
454
  for (inst=0; inst<RC.nb_nr_inst; inst++) {
455
    LOG_I(PHY,"RC.nb_nr_CC[inst:%d]:%p\n", inst, RC.gNB[inst]);
456

457
    gNB = RC.gNB[inst];
458
    gNB->ldpc_offload_flag = get_softmodem_params()->ldpc_offload_flag;
459

460
    phy_init_nr_gNB(gNB);
461

462 463
    // 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);
464

465 466
    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);
467

468 469 470 471 472 473 474 475 476
    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++) {
477 478
        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];
479
        gNB->common_vars.rxdataF[aa]     =  (c16_t *)gNB->RU_list[ru_id]->common.rxdataF[i];
480
      }
laurent's avatar
laurent committed
481
    }
482

483 484 485 486 487
    /* 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
488
    init_gNB_Tpool(inst);
laurent's avatar
laurent committed
489 490 491 492 493
  }

}

void init_gNB(int single_thread_flag,int wait_for_sync) {
494

laurent's avatar
laurent committed
495 496 497
  int inst;
  PHY_VARS_gNB *gNB;

Raymond Knopp's avatar
Raymond Knopp committed
498
  if (RC.gNB == NULL) {
499
    RC.gNB = (PHY_VARS_gNB **) calloc(1+RC.nb_nr_L1_inst, sizeof(PHY_VARS_gNB *));
500
    LOG_I(PHY,"gNB L1 structure RC.gNB allocated @ %p\n",RC.gNB);
Raymond Knopp's avatar
Raymond Knopp committed
501
  }
laurent's avatar
laurent committed
502 503

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

505
    if (RC.gNB[inst] == NULL) {
506
      RC.gNB[inst] = (PHY_VARS_gNB *) calloc(1, sizeof(PHY_VARS_gNB));
507
      LOG_I(PHY,"[nr-gnb.c] gNB structure RC.gNB[%d] allocated @ %p\n",inst,RC.gNB[inst]);
508
    }
509 510 511 512 513 514 515 516 517
    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);
518

519 520 521 522 523 524 525
    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");
526

527 528 529
    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;
530 531
    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;
532
    gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;*/
533

534
    gNB->prach_energy_counter = 0;
535 536
    gNB->chest_time = get_softmodem_params()->chest_time;
    gNB->chest_freq = get_softmodem_params()->chest_freq;
537

laurent's avatar
laurent committed
538
  }
539
  
laurent's avatar
laurent committed
540

541
  LOG_I(PHY,"[nr-gnb.c] gNB structure allocated\n");
laurent's avatar
laurent committed
542 543 544 545 546 547
}


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
548
    term_gNB_Tpool(inst);
laurent's avatar
laurent committed
549 550
  }
}