nr_ru_procedures.c 23.7 KB
Newer Older
Guy De Souza's avatar
Guy De Souza 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
/*
 * 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 ru_procedures.c
 * \brief Implementation of RU procedures
 * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas
 * \date 2011
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk
 * \note
 * \warning
 */

33 34
#include "PHY/defs_gNB.h"
#include "PHY/phy_extern.h"
Guy De Souza's avatar
Guy De Souza committed
35 36
#include "sched_nr.h"
#include "PHY/MODULATION/modulation_common.h"
37
#include "PHY/MODULATION/nr_modulation.h"
Guy De Souza's avatar
Guy De Souza committed
38 39 40
#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"

41
#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
42
#include "LAYER2/MAC/mac.h"
43
#include "common/utils/LOG/log.h"
Laurent's avatar
Laurent committed
44
#include "common/utils/system.h"
45
#include "common/utils/LOG/vcd_signal_dumper.h"
Guy De Souza's avatar
Guy De Souza committed
46 47 48 49 50 51 52 53 54 55 56 57 58

#include "T.h"

#include "assertions.h"
#include "msc.h"

#include <time.h>
// RU OFDM Modulator gNodeB

extern openair0_config_t openair0_cfg[MAX_CARDS];

extern int oai_exit;

59
void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) {
Guy De Souza's avatar
Guy De Souza committed
60

61
  NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
Guy De Souza's avatar
Guy De Souza committed
62

63
  unsigned int slot_offset,slot_offsetF;
64
  int slot = tti_tx;
Guy De Souza's avatar
Guy De Souza committed
65 66


67
  //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0) , 1 );
Guy De Souza's avatar
Guy De Souza committed
68

69 70
  slot_offset  = slot*fp->samples_per_slot;
  slot_offsetF = first_symbol*fp->ofdm_symbol_size;
Guy De Souza's avatar
Guy De Souza committed
71

72

73 74 75
  if (first_symbol>0) slot_offset += (fp->ofdm_symbol_size*first_symbol) + (fp->nb_prefix_samples0) + (fp->nb_prefix_samples*(first_symbol-1));

  LOG_D(PHY,"SFN/SF:RU:TX:%d/%d Generating slot %d (first_symbol %d num_symbols %d)\n",ru->proc.frame_tx, ru->proc.tti_tx,slot,first_symbol,num_symbols);
Guy De Souza's avatar
Guy De Souza committed
76

77 78 79 80 81 82 83 84 85 86
  if (fp->Ncp == 1) {
    PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
                 (int*)&ru->common.txdata[aa][slot_offset],
                 fp->ofdm_symbol_size,
                 num_symbols,
                 fp->nb_prefix_samples,
                 CYCLIC_PREFIX);
  }
  else {
    if (first_symbol==0) {
87
      PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
88 89 90 91 92 93 94 95 96 97 98
                   (int*)&ru->common.txdata[aa][slot_offset],
                   fp->ofdm_symbol_size,
                   1,
                   fp->nb_prefix_samples0,
                   CYCLIC_PREFIX);
      PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF+fp->ofdm_symbol_size],
                   (int*)&ru->common.txdata[aa][slot_offset+fp->nb_prefix_samples0+fp->ofdm_symbol_size],
                   fp->ofdm_symbol_size,
                   num_symbols-1,
                   fp->nb_prefix_samples,
                   CYCLIC_PREFIX);
99 100
    }
    else {
101 102 103 104 105 106
      PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
                   (int*)&ru->common.txdata[aa][slot_offset],
                   fp->ofdm_symbol_size,
                   num_symbols,
                   fp->nb_prefix_samples,
                   CYCLIC_PREFIX);
107
    }
Guy De Souza's avatar
Guy De Souza committed
108
  }
109
  //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0), 0);
Guy De Souza's avatar
Guy De Souza committed
110 111
}

112
void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx) {
Guy De Souza's avatar
Guy De Souza committed
113

WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
114
  nfapi_nr_config_request_t *cfg = &ru->gNB_list[0]->gNB_config;
115 116
  RU_proc_t  *proc  = &ru->proc;
  RU_feptx_t *feptx = proc->feptx;
Guy De Souza's avatar
Guy De Souza committed
117

118 119
  PHY_VARS_gNB *gNB;
  NR_DL_FRAME_PARMS *fp   = ru->nr_frame_parms;
Guy De Souza's avatar
Guy De Souza committed
120

121
  int slot = tti_tx;
122
  int i    = 0;
123 124
  int j    = 0;//symbol
  int aa   = 0;//logical antenna number
125
  int ret  = 0;
Francesco Mani's avatar
Francesco Mani committed
126
  int nb_antenna_ports = fp->L_ssb;
127
  int ofdm_mask_full   = (1<<(ru->nb_tx*2))-1;
128
  int txdataF_offset   = ((tti_tx%2)*fp->samples_per_slot_wCP);
Guy De Souza's avatar
Guy De Souza committed
129

130
  if (nr_slot_select(cfg,slot,frame_tx) == SF_UL) return;
131 132 133
  for (aa=0; aa<fp->Lmax; aa++) {
    memset(ru->common.txdataF[aa],0,fp->samples_per_slot_wCP*sizeof(int32_t));
  }
Guy De Souza's avatar
Guy De Souza committed
134

135
  start_meas(&ru->ofdm_total_stats);
136
  if(ru->num_gNB != 0){//L1 RU on same machine
137
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 1 );
138
    for(j=0; j<2; ++j){//half slot 
139
      for(i=0; i<ru->nb_tx; ++i){
140
        if(j == 0){
141 142 143 144
          AssertFatal((ret=pthread_mutex_lock(&feptx[i].mutex_feptx))==0,"mutex_lock return %d\n",ret);
          feptx[i].aa                      = i;
          feptx[i].index                   = i;
          feptx[i].ru                      = ru;
145
          feptx[i].symbol                  = 0;
146 147 148 149 150
          feptx[i].slot                    = slot;
          feptx[i].nb_antenna_ports        = nb_antenna_ports;
          feptx[i].instance_cnt_feptx      = 0;
          AssertFatal(pthread_cond_signal(&feptx[i].cond_feptx) == 0,"ERROR pthread_cond_signal for feptx_ofdm_thread\n");
          AssertFatal((ret=pthread_mutex_unlock(&feptx[i].mutex_feptx))==0,"mutex_lock returns %d\n",ret);
151
        }//first half
152 153 154 155 156
        else{
          AssertFatal((ret=pthread_mutex_lock(&feptx[i+ru->nb_tx].mutex_feptx))==0,"mutex_lock return %d\n",ret);
          feptx[i+ru->nb_tx].aa                      = i;
          feptx[i+ru->nb_tx].index                   = i+ru->nb_tx;
          feptx[i+ru->nb_tx].ru                      = ru;
WANG Tsu-Han's avatar
WANG Tsu-Han committed
157
          feptx[i+ru->nb_tx].symbol                  = fp->symbols_per_slot>>1;
158 159 160 161 162
          feptx[i+ru->nb_tx].slot                    = slot;
          feptx[i+ru->nb_tx].nb_antenna_ports        = nb_antenna_ports;
          feptx[i+ru->nb_tx].instance_cnt_feptx      = 0;
          AssertFatal(pthread_cond_signal(&feptx[i+ru->nb_tx].cond_feptx) == 0,"ERROR pthread_cond_signal for feptx_ofdm_thread\n");
          AssertFatal((ret=pthread_mutex_unlock(&feptx[i+ru->nb_tx].mutex_feptx))==0,"mutex_lock returns %d\n",ret);
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
        }//second half
      }//physical antenna
    }//half slot
  }//if L1 RU on same machine
  else{//(RU only machine)
    for(j=0; j<fp->symbols_per_slot; ++j){

      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+j , 1);
      start_meas(&ru->txdataF_copy_stats);
      if (ru->num_gNB == 1){
        gNB = ru->gNB_list[0];
        cfg = &gNB->gNB_config;

        for(i=0; i<nb_antenna_ports; ++i){
          memcpy((void*)&ru->common.txdataF[i][j*fp->ofdm_symbol_size],
           (void*)&gNB->common_vars.txdataF[i][j*fp->ofdm_symbol_size + txdataF_offset],
           fp->ofdm_symbol_size*sizeof(int32_t));
        }

      }//num_gNB == 1
      stop_meas(&ru->txdataF_copy_stats);
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+j , 0);

      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 1 );

      if (nr_slot_select(cfg,slot,frame_tx)==SF_DL) {
        // If this is not an S-tti
        for(i=0; i<ru->nb_tx; ++i){
          if(j%2 == 0){
            while(feptx[i].instance_cnt_feptx != -1){
              usleep(5);
            }
            AssertFatal((ret=pthread_mutex_lock(&feptx[i].mutex_feptx))==0,"mutex_lock return %d\n",ret);
            feptx[i].aa                      = i;
            feptx[i].index                   = i;
            feptx[i].ru                      = ru;
            feptx[i].symbol                  = j;
            feptx[i].slot                    = slot;
            feptx[i].nb_antenna_ports        = nb_antenna_ports;
            feptx[i].instance_cnt_feptx      = 0;
            AssertFatal(pthread_cond_signal(&feptx[i].cond_feptx) == 0,"ERROR pthread_cond_signal for feptx_ofdm_thread\n");
            AssertFatal((ret=pthread_mutex_unlock(&feptx[i].mutex_feptx))==0,"mutex_lock returns %d\n",ret);
          }
          else{
            while(feptx[i+ru->nb_tx].instance_cnt_feptx != -1){
              usleep(5);
            }
            AssertFatal((ret=pthread_mutex_lock(&feptx[i+ru->nb_tx].mutex_feptx))==0,"mutex_lock return %d\n",ret);
            feptx[i+ru->nb_tx].aa                      = i;
            feptx[i+ru->nb_tx].index                   = i+ru->nb_tx;
            feptx[i+ru->nb_tx].ru                      = ru;
            feptx[i+ru->nb_tx].symbol                  = j;
            feptx[i+ru->nb_tx].slot                    = slot;
            feptx[i+ru->nb_tx].nb_antenna_ports        = nb_antenna_ports;
            feptx[i+ru->nb_tx].instance_cnt_feptx      = 0;
            AssertFatal(pthread_cond_signal(&feptx[i+ru->nb_tx].cond_feptx) == 0,"ERROR pthread_cond_signal for feptx_ofdm_thread\n");
            AssertFatal((ret=pthread_mutex_unlock(&feptx[i+ru->nb_tx].mutex_feptx))==0,"mutex_lock returns %d\n",ret);
          }
221 222
        }
       
223 224 225 226 227 228
      }//if == SF_DL
      else {
        proc->feptx_mask = ofdm_mask_full;
      }
    }//j<fp->symbols_per_slot
  }//else (RU only machine)
Guy De Souza's avatar
Guy De Souza committed
229

230 231 232 233 234 235
  // wait all process to finish
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_feptx))==0,"mutex_lock return %d\n",ret);
  while (proc->feptx_mask != ofdm_mask_full) {
    // most of the time the thread is waiting here
    // proc->instance_cnt_rxtx is -1
    pthread_cond_wait(&proc->cond_feptx,&proc->mutex_feptx); // this unlocks mutex_rxtx while waiting and then locks it again
Guy De Souza's avatar
Guy De Souza committed
236
  }
237 238
  proc->feptx_mask = 0;
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_feptx))==0,"mutex_lock return %d\n",ret);
Guy De Souza's avatar
Guy De Souza committed
239

240
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RU_TX_OFDM_MASK, proc->feptx_mask );
Guy De Souza's avatar
Guy De Souza committed
241 242
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 0 );

Guy De Souza's avatar
Guy De Souza committed
243

Wang Tsu-Han's avatar
Wang Tsu-Han committed
244
  stop_meas(&ru->ofdm_total_stats);
Guy De Souza's avatar
Guy De Souza committed
245 246 247

}

Guy De Souza's avatar
Guy De Souza committed
248 249
static void *nr_feptx_thread(void *param) {

250 251
  RU_feptx_t *feptx = (RU_feptx_t *)param;
  RU_t       *ru;
252
  int         aa, slot, start, l, nb_antenna_ports, ret;
253
  int         i;
254 255
  int32_t ***bw;
  NR_DL_FRAME_PARMS *fp;
256
  int ofdm_mask_full;
257 258
  int txdataF_offset;
  int32_t *txdataF;
Guy De Souza's avatar
Guy De Souza committed
259 260 261 262


  while (!oai_exit) {

263
    ret = 0;
264
    if (wait_on_condition(&feptx->mutex_feptx,&feptx->cond_feptx,&feptx->instance_cnt_feptx,"NR feptx thread")<0) break;
265 266
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+feptx->index+1 , 1 );

267 268 269
    ru    = feptx->ru;
    slot  = feptx->slot;
    aa    = feptx->aa;
270
    l     = feptx->symbol;
271
    fp    = ru->nr_frame_parms;
272
    start = feptx->symbol;
273 274
    nb_antenna_ports = feptx->nb_antenna_ports;
    ofdm_mask_full   = (1<<(ru->nb_tx*2))-1;
275

276 277
    if(ru->num_gNB != 0){
      txdataF_offset = ((slot%2)*fp->samples_per_slot_wCP);
WANG Tsu-Han's avatar
WANG Tsu-Han committed
278 279
      ////////////precoding////////////
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->index+1 , 1);
280 281 282 283 284 285
      start_meas(&ru->precoding_stats);
      if (ru->nb_tx == 1) {
        AssertFatal(fp->N_ssb==ru->nb_tx,"Attempting to transmit %d SSB while Nb_tx = %d",fp->N_ssb,ru->nb_tx);
        for (int p=0; p<fp->Lmax; p++) {
          if ((fp->L_ssb >> p) & 0x01){
            memcpy((void*)&ru->common.txdataF_BF[0][l*fp->ofdm_symbol_size],
Francesco Mani's avatar
Francesco Mani committed
286
                 (void*)&ru->gNB_list[0]->common_vars.txdataF[p][txdataF_offset + l*fp->ofdm_symbol_size],
WANG Tsu-Han's avatar
WANG Tsu-Han committed
287
                 (fp->samples_per_slot_wCP>>1)*sizeof(int32_t));
288
          }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
289 290
        }
      }
291 292 293
      else {
        bw  = ru->beam_weights[0];
        txdataF = &ru->gNB_list[0]->common_vars.txdataF[0][txdataF_offset];
WANG Tsu-Han's avatar
WANG Tsu-Han committed
294
        for(i=0; i<fp->symbols_per_slot>>1; ++i){
295
          nr_beam_precoding(&txdataF,
296 297 298 299
                        ru->common.txdataF_BF,
                        fp,
                        bw,
                        slot,
300
                        l+i,
301 302
                        aa,
                        nb_antenna_ports);
303 304 305
        }
      }
      stop_meas(&ru->precoding_stats);
WANG Tsu-Han's avatar
WANG Tsu-Han committed
306
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->index+1 , 0);
Guy De Souza's avatar
Guy De Souza committed
307

WANG Tsu-Han's avatar
WANG Tsu-Han committed
308
      ////////////FEPTX////////////
309
      start_meas(&ru->ofdm_mod_stats);
WANG Tsu-Han's avatar
WANG Tsu-Han committed
310
      nr_feptx0(ru,slot,start,fp->symbols_per_slot>>1,aa);
311
      stop_meas(&ru->ofdm_mod_stats);
312

WANG Tsu-Han's avatar
WANG Tsu-Han committed
313
      if (release_thread(&feptx->mutex_feptx,&feptx->instance_cnt_feptx,"NR feptx thread")<0) break;
314

315 316 317 318 319
      AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_feptx))==0,"mutex_lock return %d\n",ret);
      ru->proc.feptx_mask |= 1<<(feptx->index);
      if(ru->proc.feptx_mask == ofdm_mask_full)
        AssertFatal(pthread_cond_signal(&ru->proc.cond_feptx) == 0,"ERROR pthread_cond_signal for precoding and ofdm finish\n");
      AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_feptx))==0,"mutex_lock returns %d\n",ret);
320 321 322 323 324

      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RU_TX_OFDM_MASK, ru->proc.feptx_mask );
    }// if L1 RU on same machine

    else{
WANG Tsu-Han's avatar
WANG Tsu-Han committed
325
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->index+1 , 1);
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
      start_meas(&ru->precoding_stats);
      if (ru->nb_tx == 1) {
        AssertFatal(fp->N_ssb==ru->nb_tx,"Attempting to transmit %d SSB while Nb_tx = %d",fp->N_ssb,ru->nb_tx);
        for (int p=0; p<fp->Lmax; p++) {
          if ((fp->L_ssb >> p) & 0x01){
            memcpy((void*)&ru->common.txdataF_BF[0][l*fp->ofdm_symbol_size],
                 (void*)&ru->common.txdataF[p][l*fp->ofdm_symbol_size],
                 fp->ofdm_symbol_size*sizeof(int32_t));
          }
        }
      }
      else {
        bw  = ru->beam_weights[0];
        nr_beam_precoding(ru->common.txdataF,
                        ru->common.txdataF_BF,
                        fp,
                        bw,
                        slot,
                        l,
                        aa,
                        nb_antenna_ports);
      }
      stop_meas(&ru->precoding_stats);
WANG Tsu-Han's avatar
WANG Tsu-Han committed
349
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->index+1 , 0);
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366


      start_meas(&ru->ofdm_mod_stats);
      nr_feptx0(ru,slot,start,1,aa);
      stop_meas(&ru->ofdm_mod_stats);

      if (release_thread(&feptx->mutex_feptx,&feptx->instance_cnt_feptx,"NR feptx thread")<0) break;

      if(l >= fp->symbols_per_slot -2){
        AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_feptx))==0,"mutex_lock return %d\n",ret);
        ru->proc.feptx_mask |= 1<<(feptx->index);
        if(ru->proc.feptx_mask == ofdm_mask_full)
          AssertFatal(pthread_cond_signal(&ru->proc.cond_feptx) == 0,"ERROR pthread_cond_signal for precoding and ofdm finish\n");
        AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_feptx))==0,"mutex_lock returns %d\n",ret);
      }
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RU_TX_OFDM_MASK, ru->proc.feptx_mask );
    }// else (RU only machine)
367
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+feptx->index+1 , 0 );
368
  }// while (oai_exit)
Guy De Souza's avatar
Guy De Souza committed
369 370 371
  return(NULL);
}

Guy De Souza's avatar
Guy De Souza committed
372

373 374
// is this supposed to generate a slot or a subframe???
// seems to be hardcoded to numerology 1 (2 slots=1 subframe)
375
void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) {
Guy De Souza's avatar
Guy De Souza committed
376
     
377
  NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms;
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
378
  nfapi_nr_config_request_t *cfg = &ru->gNB_list[0]->gNB_config;
Guy De Souza's avatar
Guy De Souza committed
379

380
  unsigned int aa=0;
Guy De Souza's avatar
Guy De Souza committed
381 382
  int slot_sizeF = (fp->ofdm_symbol_size)*
                   ((cfg->subframe_config.dl_cyclic_prefix_type.value == 1) ? 12 : 14);
383
  int slot = tti_tx;
384
  int *txdata = &ru->common.txdata[aa][slot*fp->samples_per_slot];
Guy De Souza's avatar
Guy De Souza committed
385

laurent's avatar
laurent committed
386
  if (nr_slot_select(cfg,slot, frame_tx) == SF_UL) return;
laurent's avatar
laurent committed
387

Guy De Souza's avatar
Guy De Souza committed
388
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 1 );
389
  start_meas(&ru->ofdm_mod_stats);
Guy De Souza's avatar
Guy De Souza committed
390 391 392

    //    LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot);

393
    nr_feptx0(ru,slot,0,fp->symbols_per_slot,aa);
394

Guy De Souza's avatar
Guy De Souza committed
395
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 0 );
396 397
  stop_meas(&ru->ofdm_mod_stats);

398
  LOG_D(PHY,"feptx_ofdm (TXPATH): frame %d, slot %d: txp (time %p) %d dB, txp (freq) %d dB\n",
399
	frame_tx,slot,txdata,dB_fixed(signal_energy((int32_t*)txdata,fp->samples_per_slot)),
400 401
	dB_fixed(signal_energy_nodc(ru->common.txdataF_BF[aa],2*slot_sizeF)));

Guy De Souza's avatar
Guy De Souza committed
402
}
403

Wang Tsu-Han's avatar
Wang Tsu-Han committed
404
void nr_init_feptx_thread(RU_t *ru) {
405

Wang Tsu-Han's avatar
Wang Tsu-Han committed
406 407 408
  RU_proc_t  *proc  = &ru->proc;
  RU_feptx_t *feptx = proc->feptx;
  int i = 0;
409

WANG Tsu-Han's avatar
WANG Tsu-Han committed
410
  for(i=0; i<(ru->nb_tx*2); i++){
Wang Tsu-Han's avatar
Wang Tsu-Han committed
411 412 413 414
    feptx[i].instance_cnt_feptx         = -1;
    
    pthread_mutex_init( &feptx[i].mutex_feptx, NULL);
    pthread_cond_init( &feptx[i].cond_feptx, NULL);
415

Wang Tsu-Han's avatar
Wang Tsu-Han committed
416 417
    threadCreate(&feptx[i].pthread_feptx, nr_feptx_thread, (void*)&feptx[i], "feptx", -1, OAI_PRIORITY_RT);
    LOG_I(PHY,"init feptx thread %d\n", i);
418 419 420
  }

}
421

Wang Tsu-Han's avatar
Wang Tsu-Han committed
422

423 424 425
void nr_feptx_prec(RU_t *ru,int frame,int tti_tx) {

  int l,aa;
426
  PHY_VARS_gNB **gNB_list = ru->gNB_list,*gNB;
427 428
  NR_DL_FRAME_PARMS *fp   = ru->nr_frame_parms;
  nfapi_nr_config_request_t *cfg;
429
  int32_t ***bw;
430
  int i=0;
431

Wang Tsu-Han's avatar
Wang Tsu-Han committed
432
  start_meas(&ru->precoding_stats);
433 434 435
  if (ru->num_gNB == 1){
    gNB = gNB_list[0];
    cfg = &gNB->gNB_config;
436
    if (nr_slot_select(cfg,tti_tx,frame) == SF_UL) return;
437

438 439 440 441 442
    for(i=0; i<fp->Lmax; ++i)
      memcpy((void*)ru->common.txdataF[i],
           (void*)gNB->common_vars.txdataF[i],
           fp->samples_per_slot_wCP*sizeof(int32_t));

443
    if (ru->nb_tx == 1) {
444
    
445
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 1);
446

447
      AssertFatal(fp->N_ssb==ru->nb_tx,"Attempting to transmit %d SSB while Nb_tx = %d",fp->N_ssb,ru->nb_tx);
448

449
      for (int p=0; p<fp->Lmax; p++) {
450 451 452 453 454
        if ((fp->L_ssb >> p) & 0x01){
          memcpy((void*)ru->common.txdataF_BF[0],
                 (void*)ru->common.txdataF[p],
                 fp->samples_per_slot_wCP*sizeof(int32_t));
        }
455 456
      }

457 458 459 460 461 462
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 0);
    }// if (ru->nb_tx == 1)
    else {
      bw  = ru->beam_weights[0];
      for (l=0;l<fp->symbols_per_slot;l++) {
        for (aa=0;aa<ru->nb_tx;aa++) {
463
          nr_beam_precoding(ru->common.txdataF,
464 465 466 467 468
                            ru->common.txdataF_BF,
                            fp,
                            bw,
                            tti_tx,
                            l,
469 470
                            aa,
                            fp->Lmax);
471 472 473 474
        }// for (aa=0;aa<ru->nb_tx;aa++)
      }// for (l=0;l<fp->symbols_per_slot;l++)
    }// if (ru->nb_tx == 1)
  }// if (ru->num_gNB == 1)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
475
  stop_meas(&ru->precoding_stats);
476
}
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491

void nr_fep0(RU_t *ru, int first_half) {
  
  uint8_t start_symbol, end_symbol, l, aa;
  RU_proc_t *proc       = &ru->proc;
  NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
  
  if(first_half == 1) {
    start_symbol = 0;
    end_symbol = NR_SYMBOLS_PER_SLOT/2;
  } else {
    start_symbol = NR_SYMBOLS_PER_SLOT/2;
    end_symbol = NR_SYMBOLS_PER_SLOT;
  }

492
  LOG_D(PHY,"In fep0 for slot = %d, first_half = %d, start_symbol = %d, end_symbol = %d\n", proc->tti_rx, first_half, start_symbol, end_symbol);
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 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 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
  //  printf("fep0: slot %d\n",slot);

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+proc->tti_rx, 1);

  // remove_7_5_kHz(ru,(slot&1)+(proc->tti_rx<<1));
  for (l = start_symbol; l < end_symbol; l++) {
    for (aa = 0; aa < fp->nb_antennas_rx; aa++) {
      nr_slot_fep_ul(fp,
                     ru->common.rxdata[aa],
                     ru->common.rxdataF[aa],
                     l,
                     proc->tti_rx,
                     0,
                     0);
    }
  }
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+proc->tti_rx, 0);
}


static void *nr_feprx_thread(void *param) {

  RU_t *ru = (RU_t *)param;
  RU_proc_t *proc  = &ru->proc;


  while (!oai_exit) {

    if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"NR feprx thread")<0) break;

    if (oai_exit) break;

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX1, 1 );

    nr_fep0(ru, 0);

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX1, 0 );

    if (release_thread(&proc->mutex_fep,&proc->instance_cnt_fep,"nr_feprx thread")<0) break;

    if (pthread_cond_signal(&proc->cond_fep) != 0) {
      printf("[gNB] ERROR pthread_cond_signal for nr_feprx thread exit\n");
      exit_fun( "ERROR pthread_cond_signal" );
      return NULL;
    }
  }

  return NULL;
}


void nr_init_feprx_thread(RU_t *ru) {

  RU_proc_t *proc = &ru->proc;

  proc->instance_cnt_fep = -1;
    
  pthread_mutex_init( &proc->mutex_fep, NULL);
  pthread_cond_init( &proc->cond_fep, NULL);

  threadCreate(&proc->pthread_fep, nr_feprx_thread, (void*)ru, "feprx", -1, OAI_PRIORITY_RT);
}


void nr_fep_full_2thread(RU_t *ru, int slot) {

  RU_proc_t *proc = &ru->proc;

  struct timespec wait;

  // NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;

  // if ((fp->frame_type == TDD) &&
     // (subframe_select(fp,proc->tti_rx) != SF_UL)) return;

  if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 1 );

  wait.tv_sec=0;
  wait.tv_nsec=5000000L;

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 1 );
  start_meas(&ru->ofdm_demod_stats);

  if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) {
    printf("[RU] ERROR pthread_mutex_lock for nr_feprx thread (IC %d)\n", proc->instance_cnt_fep);
    exit_fun( "error locking mutex_fep" );
    return;
  }

  if (proc->instance_cnt_fep==0) {
    printf("[RU] FEP thread busy\n");
    exit_fun("FEP thread busy");
    pthread_mutex_unlock( &proc->mutex_fep );
    return;
  }
  
  ++proc->instance_cnt_fep;


  if (pthread_cond_signal(&proc->cond_fep) != 0) {
    printf("[RU] ERROR pthread_cond_signal for nr_feprx thread\n");
    exit_fun( "ERROR pthread_cond_signal" );
    return;
  }
  //start_meas(&ru->ofdm_demod_wakeup_stats);
  
  pthread_mutex_unlock( &proc->mutex_fep );

  // call second slot in this symbol
  nr_fep0(ru, 1);

  start_meas(&ru->ofdm_demod_wait_stats);
  wait_on_busy_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"nr_feprx thread");  
  stop_meas(&ru->ofdm_demod_wait_stats);
  if(opp_enabled == 1 && ru->ofdm_demod_wakeup_stats.p_time>30*3000){
    print_meas_now(&ru->ofdm_demod_wakeup_stats,"fep wakeup",stderr);
    printf("delay in fep wait on codition in frame_rx: %d  subframe_rx: %d \n",proc->frame_rx,proc->tti_rx);
  }

  stop_meas(&ru->ofdm_demod_stats);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 0 );
}



void nr_fep_full(RU_t *ru, int slot) {

  RU_proc_t *proc = &ru->proc;
  int l, aa;
  NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;

  // if ((fp->frame_type == TDD) && 
     // (subframe_select(fp,proc->tti_rx) != SF_UL)) return;

  start_meas(&ru->ofdm_demod_stats);
  if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 1 );

  // remove_7_5_kHz(ru,proc->tti_rx<<1);
  // remove_7_5_kHz(ru,1+(proc->tti_rx<<1));

633
  for (l = 0; l < fp->symbols_per_slot; l++) {
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
    for (aa = 0; aa < fp->nb_antennas_rx; aa++) {
      nr_slot_fep_ul(fp,
                     ru->common.rxdata[aa],
                     ru->common.rxdataF[aa],
                     l,
                     proc->tti_rx,
                     0,
                     0);
    }
  }

  if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 0 );
  stop_meas(&ru->ofdm_demod_stats);
  
  
}