nr_ru_procedures.c 26 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
  slot_offset  = fp->get_samples_slot_timestamp(slot,fp,0);
70
  slot_offsetF = first_symbol*fp->ofdm_symbol_size;
Guy De Souza's avatar
Guy De Souza committed
71

72
  int abs_first_symbol = slot*fp->symbols_per_slot;
73

74
  for (uint16_t idx_sym=abs_first_symbol; idx_sym<abs_first_symbol+first_symbol; idx_sym++)
75
    slot_offset += (idx_sym%(0x7<<fp->numerology_index)) ? fp->nb_prefix_samples : fp->nb_prefix_samples0;
76

77
  slot_offset += fp->ofdm_symbol_size*first_symbol;
Guy De Souza's avatar
Guy De Souza committed
78

79 80 81
  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);
  
  if (fp->Ncp == 1)
82 83 84 85 86 87 88
    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 {
89
    if (fp->numerology_index != 0) {
90 91 92 93 94 95 96 97
      
      if (!(slot%(fp->slots_per_subframe/2))&&(first_symbol==0)) { // case where first symbol in slot has longer prefix
	apply_nr_rotation(fp,
			  (int16_t*)&ru->common.txdataF_BF[aa][slot_offsetF],
			  slot,
			  0,
			  1,
			  fp->ofdm_symbol_size);
98 99 100 101 102 103 104

        PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
                     (int*)&ru->common.txdata[aa][slot_offset],
                     fp->ofdm_symbol_size,
                     1,
                     fp->nb_prefix_samples0,
                     CYCLIC_PREFIX);
105 106 107 108 109 110 111 112

	apply_nr_rotation(fp,
			  (int16_t*)&ru->common.txdataF_BF[aa][slot_offsetF+fp->ofdm_symbol_size],
			  slot,
			  1,
			  num_symbols-1,
			  fp->ofdm_symbol_size);

113 114 115 116 117 118 119
        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);
      }
120 121 122 123 124 125 126
      else { // all symbols in slot have shorter prefix
	apply_nr_rotation(fp,
			  (int16_t*)&ru->common.txdataF_BF[aa][slot_offsetF],
			  slot,
			  first_symbol,
			  num_symbols,
			  fp->ofdm_symbol_size);
127 128 129 130 131 132 133
        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);
      }
134 135
    } // numerology_index!=0
    else { //numerology_index == 0
136 137 138 139 140 141 142 143
      for (uint16_t idx_sym=abs_first_symbol; idx_sym<abs_first_symbol+num_symbols; idx_sym++) {
        if (idx_sym%0x7) {
          PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
                       (int*)&ru->common.txdata[aa][slot_offset],
                       fp->ofdm_symbol_size,
                       1,
                       fp->nb_prefix_samples,
                       CYCLIC_PREFIX);
144 145 146 147 148 149
	  apply_nr_rotation(fp,
			    (int16_t*)&ru->common.txdata[aa][slot_offset],
			    slot,
			    idx_sym,
			    1,
			    fp->ofdm_symbol_size+fp->nb_prefix_samples);
150 151 152 153 154 155 156 157 158
          slot_offset += fp->nb_prefix_samples+fp->ofdm_symbol_size;
        }
        else {
          PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
                       (int*)&ru->common.txdata[aa][slot_offset],
                       fp->ofdm_symbol_size,
                       1,
                       fp->nb_prefix_samples0,
                       CYCLIC_PREFIX);
159 160 161 162 163 164
	  apply_nr_rotation(fp,
			    (int16_t*)&ru->common.txdata[aa][slot_offset],
			    slot,
			    0,
			    1,
			    fp->ofdm_symbol_size+fp->nb_prefix_samples0);
165 166 167
          slot_offset += fp->nb_prefix_samples0+fp->ofdm_symbol_size;
        }
      }
168
    }
Guy De Souza's avatar
Guy De Souza committed
169
  }
170 171

        
172
  //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
173 174
}

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

177
  nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
178 179
  RU_proc_t  *proc  = &ru->proc;
  RU_feptx_t *feptx = proc->feptx;
Guy De Souza's avatar
Guy De Souza committed
180

181 182
  PHY_VARS_gNB *gNB;
  NR_DL_FRAME_PARMS *fp   = ru->nr_frame_parms;
183
  
184
  int slot = tti_tx;
Guy De Souza's avatar
Guy De Souza committed
185

186
  int i    = 0;
187
  int j    = 0;//symbol
188
  int aa   = 0;//physical antenna number
189
  int ret  = 0;
190
  int ofdm_mask_full   = (1<<(ru->nb_tx*2))-1;
191
  int txdataF_offset   = ((tti_tx%2)*fp->samples_per_slot_wCP);
Guy De Souza's avatar
Guy De Souza committed
192

193
  if (nr_slot_select(cfg,frame_tx,slot) == NR_UPLINK_SLOT) return;
194
  for (aa=0; aa<ru->nb_tx; aa++) memset(ru->common.txdataF[aa],0,fp->samples_per_slot_wCP*sizeof(int32_t));
Guy De Souza's avatar
Guy De Souza committed
195

196
  start_meas(&ru->ofdm_total_stats);
Guy De Souza's avatar
Guy De Souza committed
197

198
  //if (nr_slot_select(cfg,frame_tx,slot)==NR_DOWNLINK_SLOT) {
199
    if(ru->num_gNB != 0){//L1 RU on same machine
200
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 1 );
201
      for(j=0; j<2; ++j){//half slot 
202
        for(i=0; i<ru->nb_tx; ++i){
203
          if(j == 0){
204 205 206 207
            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;
208
            feptx[i].symbol                  = 0;
209
            feptx[i].slot                    = slot;
210
            feptx[i].nb_antenna_ports        = ru->nb_tx;
211 212 213
            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);
214
          }//first half
215 216 217 218 219
          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;
220
            feptx[i+ru->nb_tx].symbol                  = fp->symbols_per_slot>>1;
221
            feptx[i+ru->nb_tx].slot                    = slot;
222
            feptx[i+ru->nb_tx].nb_antenna_ports        = ru->nb_tx;
223 224 225
            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);
226 227 228 229 230 231 232 233 234 235 236 237 238
          }//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;

239
          for(i=0; i<ru->nb_tx; ++i){
240 241 242
            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));
243
          }
Guy De Souza's avatar
Guy De Souza committed
244

245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
        }//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;
264
              feptx[i].nb_antenna_ports        = ru->nb_tx;
265 266 267 268 269 270 271 272 273 274 275 276 277 278
              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;
279
              feptx[i+ru->nb_tx].nb_antenna_ports        = ru->nb_tx;
280 281 282 283
              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);
            }
284
          }
285 286 287
        }//if == SF_DL
        else {
          proc->feptx_mask = ofdm_mask_full;
288
        }
289 290
      }//j<fp->symbols_per_slot
    }//else (RU only machine)
291
  //}
292 293 294 295 296 297
  // 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
298
  }
299 300
  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
301

302
  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
303 304
  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
305

Wang Tsu-Han's avatar
Wang Tsu-Han committed
306
  stop_meas(&ru->ofdm_total_stats);
Guy De Souza's avatar
Guy De Souza committed
307 308 309

}

Guy De Souza's avatar
Guy De Souza committed
310 311
static void *nr_feptx_thread(void *param) {

312 313
  RU_feptx_t *feptx = (RU_feptx_t *)param;
  RU_t       *ru;
314
  int         aa, slot, start, l, nb_antenna_ports, ret;
315
  int         i;
316 317
  int32_t ***bw;
  NR_DL_FRAME_PARMS *fp;
318
  int ofdm_mask_full;
319 320
  int txdataF_offset;
  int32_t *txdataF;
Guy De Souza's avatar
Guy De Souza committed
321
  while (!oai_exit) {
322
    ret = 0;
323
    if (wait_on_condition(&feptx->mutex_feptx,&feptx->cond_feptx,&feptx->instance_cnt_feptx,"NR feptx thread")<0) break;
324 325
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+feptx->index+1 , 1 );

326 327
    AssertFatal(feptx->ru->nb_log_antennas>0 && feptx->ru->nb_log_antennas < 13,"ru->nb_log_antennas is %d\n", feptx->ru->nb_log_antennas);

328 329 330
    ru    = feptx->ru;
    slot  = feptx->slot;
    aa    = feptx->aa;
331
    l     = feptx->symbol;
332
    fp    = ru->nr_frame_parms;
333
    start = feptx->symbol;
334 335
    nb_antenna_ports = feptx->nb_antenna_ports;
    ofdm_mask_full   = (1<<(ru->nb_tx*2))-1;
336

337 338
    if(ru->num_gNB != 0){
      txdataF_offset = ((slot%2)*fp->samples_per_slot_wCP);
WANG Tsu-Han's avatar
WANG Tsu-Han committed
339 340
      ////////////precoding////////////
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->index+1 , 1);
341
      start_meas(&ru->precoding_stats);
342
      if (ru->nb_tx == 1 && ru->nb_log_antennas == 1) {
343
            memcpy((void*)&ru->common.txdataF_BF[0][l*fp->ofdm_symbol_size],
344
                 (void*)&ru->gNB_list[0]->common_vars.txdataF[0][txdataF_offset + l*fp->ofdm_symbol_size],
WANG Tsu-Han's avatar
WANG Tsu-Han committed
345
                 (fp->samples_per_slot_wCP>>1)*sizeof(int32_t));
Wang Tsu-Han's avatar
Wang Tsu-Han committed
346
      }
347 348 349
      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
350
        for(i=0; i<fp->symbols_per_slot>>1; ++i){
351
          nr_beam_precoding(&txdataF,
352 353 354 355
                        ru->common.txdataF_BF,
                        fp,
                        bw,
                        slot,
356
                        l+i,
357 358
                        aa,
                        nb_antenna_ports);
359 360 361
        }
      }
      stop_meas(&ru->precoding_stats);
WANG Tsu-Han's avatar
WANG Tsu-Han committed
362
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->index+1 , 0);
363

WANG Tsu-Han's avatar
WANG Tsu-Han committed
364
      ////////////FEPTX////////////
365
      start_meas(&ru->ofdm_mod_stats);
WANG Tsu-Han's avatar
WANG Tsu-Han committed
366
      nr_feptx0(ru,slot,start,fp->symbols_per_slot>>1,aa);
367
      stop_meas(&ru->ofdm_mod_stats);
368

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

371 372 373 374 375
      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);
376 377 378 379 380

      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
381
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->index+1 , 1);
382
      start_meas(&ru->precoding_stats);
383
      if (ru->nb_tx == 1 && ru->nb_log_antennas) {
384
            memcpy((void*)&ru->common.txdataF_BF[0][l*fp->ofdm_symbol_size],
385
                 (void*)&ru->common.txdataF[0][l*fp->ofdm_symbol_size],
386 387 388 389 390 391 392 393 394 395 396 397 398 399
                 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
400
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->index+1 , 0);
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417


      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)
418
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+feptx->index+1 , 0 );
419
  }// while (oai_exit)
Guy De Souza's avatar
Guy De Souza committed
420 421 422
  return(NULL);
}

Guy De Souza's avatar
Guy De Souza committed
423

424 425
// is this supposed to generate a slot or a subframe???
// seems to be hardcoded to numerology 1 (2 slots=1 subframe)
426
void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) {
Guy De Souza's avatar
Guy De Souza committed
427
     
428
  nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
429
  NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms;
430
  int cyclic_prefix_type = NFAPI_CP_NORMAL;
Guy De Souza's avatar
Guy De Souza committed
431

432
  unsigned int aa=0;
Guy De Souza's avatar
Guy De Souza committed
433
  int slot_sizeF = (fp->ofdm_symbol_size)*
434
                   ((cyclic_prefix_type == 1) ? 12 : 14);
435
  int slot = tti_tx;
436
  int *txdata = &ru->common.txdata[aa][fp->get_samples_slot_timestamp(slot,fp,0)];
Guy De Souza's avatar
Guy De Souza committed
437

438
  if (nr_slot_select(cfg,frame_tx,slot) == NR_UPLINK_SLOT) return;
laurent's avatar
laurent committed
439

Guy De Souza's avatar
Guy De Souza committed
440
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 1 );
441
  start_meas(&ru->ofdm_mod_stats);
Guy De Souza's avatar
Guy De Souza committed
442 443 444 445


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

446
  nr_feptx0(ru,slot,0,NR_NUMBER_OF_SYMBOLS_PER_SLOT,aa);
447

Guy De Souza's avatar
Guy De Souza committed
448
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 0 );
449 450
  stop_meas(&ru->ofdm_mod_stats);

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

Guy De Souza's avatar
Guy De Souza committed
455
}
456

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

Wang Tsu-Han's avatar
Wang Tsu-Han committed
459 460 461
  RU_proc_t  *proc  = &ru->proc;
  RU_feptx_t *feptx = proc->feptx;
  int i = 0;
462

WANG Tsu-Han's avatar
WANG Tsu-Han committed
463
  for(i=0; i<(ru->nb_tx*2); i++){
Wang Tsu-Han's avatar
Wang Tsu-Han committed
464 465 466 467
    feptx[i].instance_cnt_feptx         = -1;
    
    pthread_mutex_init( &feptx[i].mutex_feptx, NULL);
    pthread_cond_init( &feptx[i].cond_feptx, NULL);
468

Wang Tsu-Han's avatar
Wang Tsu-Han committed
469 470
    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);
471 472 473
  }

}
474

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

476
void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx) {
477 478

  int l,aa;
479
  PHY_VARS_gNB **gNB_list = ru->gNB_list,*gNB;
480
  NR_DL_FRAME_PARMS *fp   = ru->nr_frame_parms;
481
  nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
482
  int32_t ***bw;
483
  int i=0;
484
  int slot_tx = tti_tx;
485
  int txdataF_offset   = ((tti_tx%2)*fp->samples_per_slot_wCP);
486

Wang Tsu-Han's avatar
Wang Tsu-Han committed
487
  start_meas(&ru->precoding_stats);
488
  AssertFatal(ru->nb_log_antennas > 0,"ru->nb_log_antennas is 0!\n");
489 490
  if (ru->num_gNB == 1){
    gNB = gNB_list[0];
491

492
    if (nr_slot_select(cfg,frame_tx,slot_tx) == NR_UPLINK_SLOT) return;
493

494
    for(i=0; i<ru->nb_log_antennas; ++i)
495
      memcpy((void*)ru->common.txdataF[i],
496
           (void*)&gNB->common_vars.txdataF[i][txdataF_offset],
497 498
           fp->samples_per_slot_wCP*sizeof(int32_t));

499
    if (ru->nb_tx == 1 && ru->nb_log_antennas == 1) {
500
    
501
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 1);
502

503 504 505
      memcpy((void*)ru->common.txdataF_BF[0],
             (void*)ru->common.txdataF[0],
             fp->samples_per_slot_wCP*sizeof(int32_t));
506

507 508 509 510 511 512
      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++) {
513
          nr_beam_precoding(ru->common.txdataF,
514 515 516 517 518
                            ru->common.txdataF_BF,
                            fp,
                            bw,
                            tti_tx,
                            l,
519
                            aa,
520
                            ru->nb_log_antennas);
521 522 523 524
        }// 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
525
  stop_meas(&ru->precoding_stats);
526
}
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541

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;
  }

542
  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);
543 544 545 546 547 548 549 550 551 552 553 554
  //  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,
555
                     ru->N_TA_offset,
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
                     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) &&
616
     // (subframe_select(fp,proc->tti_rx) != NR_UPLINK_SLOT)) return;
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674

  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) && 
675
     // (subframe_select(fp,proc->tti_rx) != NR_UPLINK_SLOT)) return;
676

677 678
  LOG_D(PHY,"In fep_full for slot = %d\n", proc->tti_rx);

679 680 681 682 683 684
  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));

685
  for (l = 0; l < fp->symbols_per_slot; l++) {
686 687 688 689 690 691
    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,
692
                     ru->N_TA_offset,
693 694 695 696 697 698 699 700
                     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);
  
  
701
}