nr-gnb.c 20.6 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
  start_meas(&gNB->slot_indication_stats);
135
  ifi->NR_slot_indication(module_id, CC_id, frame_tx, slot_tx);
136
  stop_meas(&gNB->slot_indication_stats);
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
  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;
161 162 163 164 165
    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;
166 167 168
    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);
169
  }
170
  /* this thread is done with the sched_info, decrease the reference counter */
171
  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);
172
  deref_sched_response(info->sched_response_id);
173 174 175
}


176 177
void *L1_rx_thread(void *arg) 
{
178 179 180 181
  PHY_VARS_gNB *gNB = (PHY_VARS_gNB*)arg;

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

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

  // *******************************************************************
224

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

  }
  // ****************************************
234 235

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

240 241
    // UE-specific RX processing for subframe n
    // TODO: check if this is correct for PARALLEL_RU_L1_TRX_SPLIT
242 243

    // Do PRACH RU processing
244
    L1_nr_prach_procedures(gNB,frame_rx,slot_rx);
245

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

263 264 265 266 267 268 269 270 271 272 273
    // 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);
274
    syncMsg->gNB = gNB;
275 276 277 278 279
    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
280
  }
281

282 283
  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
284
}
285

286 287 288 289 290
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);
291 292 293 294 295
  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);
296 297
  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);
298
  output += print_meas_log(&gNB->slot_indication_stats, "Slot Indication", NULL, NULL, output, end - output);
299 300
  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
301
  output += print_meas_log(&gNB->rx_prach, "PRACH RX", NULL, NULL, output, end - output);
302 303
  if (ru->feprx)
    output += print_meas_log(&ru->ofdm_demod_stats, "feprx", NULL, NULL, output, end - output);
304

305
  if (ru->feptx_prec) {
306
    output += print_meas_log(&ru->precoding_stats,"feptx_prec",NULL,NULL, output, end - output);
307 308 309
  }

  if (ru->feptx_ofdm) {
310 311 312
    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);
313
  }
314

315 316
  if (ru->fh_north_asynch_in)
    output += print_meas_log(&ru->rx_fhaul,"rx_fhaul",NULL,NULL, output, end - output);
317

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

320
  if (ru->fh_north_out) {
321 322
    output += print_meas_log(&ru->compression,"compression",NULL,NULL, output, end - output);
    output += print_meas_log(&ru->transport,"transport",NULL,NULL, output, end - output);
323
  }
324
  return output - begin;
325 326
}

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

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

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

375
  // L1 RX result FIFO
376
  initNotifiedFIFO(&gNB->resp_L1);
377
  // L1 TX result FIFO 
378 379 380
  initNotifiedFIFO(&gNB->L1_tx_free);
  initNotifiedFIFO(&gNB->L1_tx_filled);
  initNotifiedFIFO(&gNB->L1_tx_out);
381 382 383 384 385 386 387 388 389 390 391 392 393 394
  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
395

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

Sakthivel Velumani's avatar
Sakthivel Velumani committed
399
}
laurent's avatar
laurent committed
400 401


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

  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
415 416
}

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

447 448
  if(NFAPI_MODE == NFAPI_MODE_PNF)
    RC.nb_nr_inst = 1;
laurent's avatar
laurent committed
449
  for (inst=0; inst<RC.nb_nr_inst; inst++) {
450
    LOG_I(PHY,"RC.nb_nr_CC[inst:%d]:%p\n", inst, RC.gNB[inst]);
451

452
    gNB = RC.gNB[inst];
453
    gNB->ldpc_offload_flag = get_softmodem_params()->ldpc_offload_flag;
454

455
    phy_init_nr_gNB(gNB);
456

457 458
    // 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);
459

460 461
    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);
462

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

478 479 480 481 482
    /* 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
483
    init_gNB_Tpool(inst);
laurent's avatar
laurent committed
484 485 486 487 488
  }

}

void init_gNB(int single_thread_flag,int wait_for_sync) {
489

laurent's avatar
laurent committed
490 491 492
  int inst;
  PHY_VARS_gNB *gNB;

Raymond Knopp's avatar
Raymond Knopp committed
493
  if (RC.gNB == NULL) {
494
    RC.gNB = (PHY_VARS_gNB **) calloc(1+RC.nb_nr_L1_inst, sizeof(PHY_VARS_gNB *));
495
    LOG_I(PHY,"gNB L1 structure RC.gNB allocated @ %p\n",RC.gNB);
Raymond Knopp's avatar
Raymond Knopp committed
496
  }
laurent's avatar
laurent committed
497 498

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

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

514 515 516 517 518 519 520
    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");
521

522 523 524
    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;
525 526
    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;
527
    gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;*/
528

529
    gNB->prach_energy_counter = 0;
530 531
    gNB->chest_time = get_softmodem_params()->chest_time;
    gNB->chest_freq = get_softmodem_params()->chest_freq;
532

laurent's avatar
laurent committed
533
  }
534
  
laurent's avatar
laurent committed
535

536
  LOG_I(PHY,"[nr-gnb.c] gNB structure allocated\n");
laurent's avatar
laurent committed
537 538 539 540 541 542
}


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
543
    term_gNB_Tpool(inst);
laurent's avatar
laurent committed
544 545
  }
}