nr_init.c 47.8 KB
Newer Older
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
#include "executables/nr-softmodem-common.h"
23
#include "common/utils/nr/nr_common.h"
24
#include "common/ran_context.h"
25
#include "PHY/defs_gNB.h"
26
#include "PHY/NR_REFSIG/nr_refsig.h"
27
#include "PHY/INIT/nr_phy_init.h"
Guy De Souza's avatar
Guy De Souza committed
28
#include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h"
Francesco Mani's avatar
Francesco Mani committed
29
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
30
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
31
#include "PHY/NR_ESTIMATION/nr_ul_estimation.h"
32
#include "openair1/PHY/MODULATION/nr_modulation.h"
33
#include "openair1/PHY/defs_RU.h"
34
#include "openair1/PHY/CODING/nrLDPC_extern.h"
35 36
#include "assertions.h"
#include <math.h>
37
#include <complex.h>
38
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
39
#include "PHY/NR_REFSIG/nr_refsig.h"
40
#include "SCHED_NR/fapi_nr_l1.h"
41
#include "nfapi_nr_interface.h"
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
42

dir's avatar
dir committed
43 44
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"

45 46 47

int l1_north_init_gNB() {

48
  if (RC.nb_nr_L1_inst > 0 &&  RC.gNB != NULL) {
49

WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
50
    AssertFatal(RC.nb_nr_L1_inst>0,"nb_nr_L1_inst=%d\n",RC.nb_nr_L1_inst);
51
    AssertFatal(RC.gNB!=NULL,"RC.gNB is null\n");
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
52
    LOG_I(PHY,"%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst);
53

54
    for (int i=0; i<RC.nb_nr_L1_inst; i++) {
55 56
      AssertFatal(RC.gNB[i]!=NULL,"RC.gNB[%d] is null\n",i);

57 58
      if ((RC.gNB[i]->if_inst =  NR_IF_Module_init(i))<0) return(-1);
      
59
      LOG_I(PHY,"%s() RC.gNB[%d] installing callbacks\n", __FUNCTION__, i);
60 61
      RC.gNB[i]->if_inst->NR_PHY_config_req = nr_phy_config_request;
      RC.gNB[i]->if_inst->NR_Schedule_response = nr_schedule_response;
62
    }
63
  } else {
64
    LOG_I(PHY,"%s() Not installing PHY callbacks - RC.nb_nr_L1_inst:%d RC.gNB:%p\n", __FUNCTION__, RC.nb_nr_L1_inst, RC.gNB);
65
  }
66

67 68 69
  return(0);
}

70 71
NR_gNB_PHY_STATS_t *get_phy_stats(PHY_VARS_gNB *gNB, uint16_t rnti)
{
francescomani's avatar
francescomani committed
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
  NR_gNB_PHY_STATS_t *stats;
  int first_free = -1;
  for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
    stats = &gNB->phy_stats[i];
    if (stats->active && stats->rnti == rnti)
      return stats;
    else if (!stats->active && first_free == -1)
      first_free = i;
  }
  // new stats
  AssertFatal(first_free >= 0, "PHY statistics list is full\n");
  stats = &gNB->phy_stats[first_free];
  stats->active = true;
  stats->rnti = rnti;
  memset(&stats->dlsch_stats, 0, sizeof(stats->dlsch_stats));
  memset(&stats->ulsch_stats, 0, sizeof(stats->ulsch_stats));
  memset(&stats->uci_stats, 0, sizeof(stats->uci_stats));
  return stats;
90 91
}

francescomani's avatar
francescomani committed
92 93 94 95 96
void reset_active_stats(PHY_VARS_gNB *gNB, int frame)
{
  // disactivate PHY stats if UE is inactive for a given number of frames
  for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
    NR_gNB_PHY_STATS_t *stats = &gNB->phy_stats[i];
francescomani's avatar
francescomani committed
97
    if (stats->active && (((frame - stats->frame + 1024) % 1024) > NUMBER_FRAMES_PHY_UE_INACTIVE))
francescomani's avatar
francescomani committed
98 99 100 101
      stats->active = false;
  }
}

102
int init_codebook_gNB(PHY_VARS_gNB *gNB) {
103 104

  if(gNB->frame_parms.nb_antennas_tx>1){
francescomani's avatar
francescomani committed
105
    int CSI_RS_antenna_ports = gNB->frame_parms.nb_antennas_tx;
106
    //NR Codebook Generation for codebook type1 SinglePanel
107 108
    int N1 = gNB->ap_N1;
    int N2 = gNB->ap_N2;
109 110 111 112 113 114
    //Uniform Planner Array: UPA
    //    X X X X ... X
    //    X X X X ... X
    // N2 . . . . ... .
    //    X X X X ... X
    //   |<-----N1---->|
115
    int x_polarization = gNB->ap_XP;
sfn's avatar
sfn committed
116
    //Get the uniform planar array parameters
117 118
    // To be confirmed
    int O2 = N2 > 1? 4 : 1; //Vertical beam oversampling (1 or 4)
francescomani's avatar
francescomani committed
119
    int O1 = CSI_RS_antenna_ports > 2 ? 4 : 1; //Horizontal beam oversampling (1 or 4)
120 121 122
    AssertFatal(CSI_RS_antenna_ports == N1*N2*x_polarization,
                "Nb of antenna ports at PHY %d does not correspond to what passed down with fapi %d\n",
                 N1*N2*x_polarization, CSI_RS_antenna_ports);
123

124 125 126 127 128 129 130 131 132
    // Generation of codebook Type1 with codebookMode 1 (CSI_RS_antenna_ports < 16)
    if (CSI_RS_antenna_ports < 16) {
      //Generate DFT vertical beams
      //ll: index of a vertical beams vector (represented by i1_1 in TS 38.214)
      double complex v[N1*O1][N1];
      for (int ll=0; ll<N1*O1; ll++) { //i1_1
        for (int nn=0; nn<N1; nn++) {
          v[ll][nn] = cexp(I*(2*M_PI*nn*ll)/(N1*O1));
          //printf("v[%d][%d] = %f +j %f\n", ll,nn, creal(v[ll][nn]),cimag(v[ll][nn]));
133
        }
134
      }
135 136 137 138 139 140
      //Generate DFT Horizontal beams
      //mm: index of a Horizontal beams vector (represented by i1_2 in TS 38.214)
      double complex u[N2*O2][N2];
      for (int mm=0; mm<N2*O2; mm++) { //i1_2
        for (int nn=0; nn<N2; nn++) {
          u[mm][nn] = cexp(I*(2*M_PI*nn*mm)/(N2*O2));
141
              //printf("u[%d][%d] = %f +j %f\n", mm,nn, creal(u[mm][nn]),cimag(u[mm][nn]));
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
        }
      }
      //Generate co-phasing angles
      //i_2: index of a co-phasing vector
      //i1_1, i1_2, and i_2 are reported from UEs
      double complex theta_n[4];
      for (int nn=0; nn<4; nn++) {
        theta_n[nn] = cexp(I*M_PI*nn/2);
        //printf("theta_n[%d] = %f +j %f\n", nn, creal(theta_n[nn]),cimag(theta_n[nn]));
      }
      //Kronecker product v_lm
      double complex v_lm[N1*O1][N2*O2][N2*N1];
      //v_ll_mm_codebook denotes the elements of a precoding matrix W_i1,1_i_1,2
      for(int ll=0; ll<N1*O1; ll++) { //i_1_1
        for (int mm=0; mm<N2*O2; mm++) { //i_1_2
          for (int nn1=0; nn1<N1; nn1++) {
            for (int nn2=0; nn2<N2; nn2++) {
              //printf("indx %d \n",nn1*N2+nn2);
              v_lm[ll][mm][nn1*N2+nn2] = v[ll][nn1]*u[mm][nn2];
              //printf("v_lm[%d][%d][%d] = %f +j %f\n",ll,mm, nn1*N2+nn2, creal(v_lm[ll][mm][nn1*N2+nn2]),cimag(v_lm[ll][mm][nn1*N2+nn2]));
162
            }
163
          }
164 165
        }
      }
166

167
      int max_mimo_layers = (CSI_RS_antenna_ports<NR_MAX_NB_LAYERS) ? CSI_RS_antenna_ports : NR_MAX_NB_LAYERS;
168

169
      gNB->nr_mimo_precoding_matrix = (int32_t ***)malloc16(max_mimo_layers * sizeof(int32_t **));
170 171 172 173 174
      int32_t ***mat = gNB->nr_mimo_precoding_matrix;
      double complex res_code;

      //Table 5.2.2.2.1-5:
      //Codebook for 1-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS
175 176
      gNB->pmiq_size[0] = N1*O1*N2*O2*4+1;
      mat[0] = (int32_t **)malloc16(gNB->pmiq_size[0]*sizeof(int32_t *));
177 178 179 180 181 182

      //pmi=0 corresponds to unit matrix
      mat[0][0] = (int32_t *)calloc(2*N1*N2,sizeof(int32_t));
      for(int j_col=0; j_col<1; j_col++) { //1 layer
        for (int i_rows=0; i_rows<2*N1*N2; i_rows++) { //2-x polarized antenna
          if(j_col==i_rows) {
sfn's avatar
sfn committed
183
            mat[0][0][i_rows+j_col] = 0x7fff;
184
          }
185 186
        }
      }
187

188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
      for(int ll=0; ll<N1*O1; ll++) { //i_1_1
        for (int mm=0; mm<N2*O2; mm++) { //i_1_2
          for (int nn=0; nn<4; nn++) {
            int pmiq = 1+ll*N2*O2*4+mm*4+nn;
            mat[0][pmiq] = (int32_t *)malloc16((2*N1*N2)*1*sizeof(int32_t));
            LOG_D(PHY, "layer 1 Codebook pmiq = %d\n",pmiq);
            for (int len=0; len<N1*N2; len++) {
              res_code=sqrt(1/(double)CSI_RS_antenna_ports)*v_lm[ll][mm][len];
              if (creal(res_code)>0)
                ((short*) &mat[0][pmiq][len])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
              else
                ((short*) &mat[0][pmiq][len])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
              if (cimag(res_code)>0)
                ((short*) &mat[0][pmiq][len])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
              else
                ((short*) &mat[0][pmiq][len])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
204 205
              LOG_D(PHY, "1 Layer Precoding Matrix[0][pmi %d][antPort %d]= %f+j %f -> Fixed Point %d+j %d \n",
                    pmiq, len, creal(res_code), cimag(res_code),((short*) &mat[0][pmiq][len])[0],((short*) &mat[0][pmiq][len])[1]);
206
            }
207

208 209 210 211 212 213 214 215 216 217
            for(int len=N1*N2; len<2*N1*N2; len++) {
              res_code=sqrt(1/(double)CSI_RS_antenna_ports)*theta_n[nn]*v_lm[ll][mm][len-N1*N2];
              if (creal(res_code)>0)
                ((short*) &mat[0][pmiq][len])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
              else
                ((short*) &mat[0][pmiq][len])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
              if (cimag(res_code)>0)
                ((short*) &mat[0][pmiq][len])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
              else
                ((short*) &mat[0][pmiq][len])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
218 219
              LOG_D(PHY, "1 Layer Precoding Matrix[0][pmi %d][antPort %d]= %f+j %f -> Fixed Point %d+j %d \n",
                    pmiq, len, creal(res_code), cimag(res_code),((short*) &mat[0][pmiq][len])[0],((short*) &mat[0][pmiq][len])[1]);
220 221
            }
          }
222 223
        }
      }
224

225 226 227
      int llc = 0;
      int mmc = 0;
      double complex phase_sign = 0;
228 229
      //Table 5.2.2.2.1-6:
      //Codebook for 2-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS
sfn's avatar
sfn committed
230 231 232
      //Compute the code book size for generating 2 layers out of Tx antenna ports

      //pmi_size is computed as follows
233
      gNB->pmiq_size[1] = 1;//1 for unity matrix
sfn's avatar
sfn committed
234 235 236 237 238
      for(int llb=0; llb<N1*O1; llb++) { //i_1_1
        for (int mmb=0; mmb<N2*O2; mmb++) { //i_1_2
          for(int ll=0; ll<N1*O1; ll++) { //i_1_1
            for (int mm=0; mm<N2*O2; mm++) { //i_1_2
              for (int nn=0; nn<2; nn++) {
239
                if((llb != ll) || (mmb != mm) || ((N1 == 1) && (N2 == 1))) gNB->pmiq_size[1] += 1;
sfn's avatar
sfn committed
240 241 242 243 244
              }
            }
          }
        }
      }
245
      mat[1] = (int32_t **)malloc16(gNB->pmiq_size[1]*sizeof(int32_t *));
246 247 248 249 250 251

      //pmi=0 corresponds to unit matrix
      mat[1][0] = (int32_t *)calloc((2*N1*N2)*(2),sizeof(int32_t));
      for(int j_col=0; j_col<2; j_col++) { //2 layers
        for (int i_rows=0; i_rows<2*N1*N2; i_rows++) { //2-x polarized antenna
          if(j_col==i_rows) {
sfn's avatar
sfn committed
252
            mat[1][0][i_rows*2+j_col] = 0x7fff;
253 254 255
          }
        }
      }
256

sfn's avatar
sfn committed
257 258
      //pmi=1,...,pmi_size, we construct
      int pmiq = 0;
259 260 261 262 263
      for(int llb=0; llb<N1*O1; llb++) { //i_1_1
        for (int mmb=0; mmb<N2*O2; mmb++) { //i_1_2
          for(int ll=0; ll<N1*O1; ll++) { //i_1_1
            for (int mm=0; mm<N2*O2; mm++) { //i_1_2
              for (int nn=0; nn<2; nn++) {
sfn's avatar
sfn committed
264
                if((llb != ll) || (mmb != mm) || ((N1 == 1) && (N2 == 1))){
sfn's avatar
sfn committed
265 266
                  pmiq += 1;
                  mat[1][pmiq] = (int32_t *)malloc16((2*N1*N2)*(2)*sizeof(int32_t));
267
                  LOG_D(PHY, "layer 2 Codebook pmiq = %d\n",pmiq);
sfn's avatar
sfn committed
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
                  for(int j_col=0; j_col<2; j_col++) {
                    if (j_col==0) {
                      llc = llb;
                      mmc = mmb;
                      phase_sign = 1;
                    }
                    if (j_col==1) {
                      llc = ll;
                      mmc = mm;
                      phase_sign = -1;
                    }
                    for (int i_rows=0; i_rows<N1*N2; i_rows++) {
                      res_code=sqrt(1/(double)(2*CSI_RS_antenna_ports))*v_lm[llc][mmc][i_rows];
                      if (creal(res_code)>0)
                        ((short*) &mat[1][pmiq][i_rows*2+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
                      else
                        ((short*) &mat[1][pmiq][i_rows*2+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
                      if (cimag(res_code)>0)
                        ((short*) &mat[1][pmiq][i_rows*2+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
                      else
                        ((short*) &mat[1][pmiq][i_rows*2+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
289 290
                      LOG_D(PHY, "2 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
                            pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[1][pmiq][i_rows*2+j_col])[0],((short*) &mat[1][pmiq][i_rows*2+j_col])[1]);
sfn's avatar
sfn committed
291 292 293 294 295 296 297 298 299 300 301
                    }
                    for (int i_rows=N1*N2; i_rows<2*N1*N2; i_rows++) {
                      res_code=sqrt(1/(double)(2*CSI_RS_antenna_ports))*(phase_sign)*theta_n[nn]*v_lm[llc][mmc][i_rows-N1*N2];
                      if (creal(res_code)>0)
                        ((short*) &mat[1][pmiq][i_rows*2+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
                      else
                        ((short*) &mat[1][pmiq][i_rows*2+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
                      if (cimag(res_code)>0)
                        ((short*) &mat[1][pmiq][i_rows*2+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
                      else
                        ((short*) &mat[1][pmiq][i_rows*2+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
302 303
                      LOG_D(PHY, "2 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
                            pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[1][pmiq][i_rows*2+j_col])[0],((short*) &mat[1][pmiq][i_rows*2+j_col])[1]);
sfn's avatar
sfn committed
304
                    }
305
                  }
306 307 308 309
                }
              }
            }
          }
310 311
        }
      }
312

313 314
      //Table 5.2.2.2.1-7:
      //Codebook for 3-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS
315
      if(max_mimo_layers>=3) {
316

sfn's avatar
sfn committed
317
        //pmi_size is computed as follows
318
        gNB->pmiq_size[2] = 1;//unity matrix
sfn's avatar
sfn committed
319 320 321 322 323
        for(int llb=0; llb<N1*O1; llb++) { //i_1_1
          for (int mmb=0; mmb<N2*O2; mmb++) { //i_1_2
            for(int ll=0; ll<N1*O1; ll++) { //i_1_1
              for (int mm=0; mm<N2*O2; mm++) { //i_1_2
                for (int nn=0; nn<2; nn++) {
324
                  if((llb != ll) || (mmb != mm)) gNB->pmiq_size[2] += 1;
sfn's avatar
sfn committed
325 326 327 328 329
                }
              }
            }
          }
        }
330
        mat[2] = (int32_t **)malloc16(gNB->pmiq_size[2]*sizeof(int32_t *));
331 332 333 334 335
        //pmi=0 corresponds to unit matrix
        mat[2][0] = (int32_t *)calloc((2*N1*N2)*(3),sizeof(int32_t));
        for(int j_col=0; j_col<3; j_col++) { //3 layers
          for (int i_rows=0; i_rows<2*N1*N2; i_rows++) { //2-x polarized antenna
            if(j_col==i_rows) {
sfn's avatar
sfn committed
336
              mat[2][0][i_rows*3+j_col] = 0x7fff;
337
            }
338 339
          }
        }
340

sfn's avatar
sfn committed
341
        pmiq = 0;
342 343 344 345 346 347
        //pmi=1,...,pmi_size are computed as follows
        for(int llb=0; llb<N1*O1; llb++) { //i_1_1
          for (int mmb=0; mmb<N2*O2; mmb++) { //i_1_2
            for(int ll=0; ll<N1*O1; ll++) { //i_1_1
              for (int mm=0; mm<N2*O2; mm++) { //i_1_2
                for (int nn=0; nn<2; nn++) {
sfn's avatar
sfn committed
348 349 350
                  if((llb != ll) || (mmb != mm)){
                    pmiq += 1;
                    mat[2][pmiq] = (int32_t *)malloc16((2*N1*N2)*(3)*sizeof(int32_t));
351
                    LOG_D(PHY, "layer 3 Codebook pmiq = %d\n",pmiq);
sfn's avatar
sfn committed
352 353 354 355 356 357 358 359 360 361 362
                    for(int j_col=0; j_col<3; j_col++) {
                      if (j_col==0) {
                        llc = llb;
                        mmc = mmb;
                        phase_sign = 1;
                      }
                      if (j_col==1) {
                        llc = ll;
                        mmc = mm;
                        phase_sign = 1;
                      }
sfn's avatar
sfn committed
363 364 365
                      if (j_col==2) {
                        llc = ll;
                        mmc = mm;
sfn's avatar
sfn committed
366 367 368 369 370 371 372 373 374 375 376 377
                        phase_sign = -1;
                      }
                      for (int i_rows=0; i_rows<N1*N2; i_rows++) {
                        res_code=sqrt(1/(double)(3*CSI_RS_antenna_ports))*v_lm[llc][mmc][i_rows];
                        if (creal(res_code)>0)
                          ((short*) &mat[2][pmiq][i_rows*3+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
                        else
                          ((short*) &mat[2][pmiq][i_rows*3+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
                        if (cimag(res_code)>0)
                          ((short*) &mat[2][pmiq][i_rows*3+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
                        else
                          ((short*) &mat[2][pmiq][i_rows*3+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
378 379
                        LOG_D(PHY, "3 Layer Precoding Matrix[2][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
                              pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[2][pmiq][i_rows*3+j_col])[0],((short*) &mat[2][pmiq][i_rows*3+j_col])[1]);
sfn's avatar
sfn committed
380 381 382 383 384 385 386 387 388 389 390
                      }
                      for (int i_rows=N1*N2; i_rows<2*N1*N2; i_rows++) {
                        res_code=sqrt(1/(double)(3*CSI_RS_antenna_ports))*(phase_sign)*theta_n[nn]*v_lm[llc][mmc][i_rows-N1*N2];
                        if (creal(res_code)>0)
                          ((short*) &mat[2][pmiq][i_rows*3+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
                        else
                          ((short*) &mat[2][pmiq][i_rows*3+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
                        if (cimag(res_code)>0)
                          ((short*) &mat[2][pmiq][i_rows*3+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
                        else
                          ((short*) &mat[2][pmiq][i_rows*3+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
391 392
                        LOG_D(PHY, "3 Layer Precoding Matrix[2][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
                              pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[2][pmiq][i_rows*3+j_col])[0],((short*) &mat[2][pmiq][i_rows*3+j_col])[1]);
sfn's avatar
sfn committed
393
                      }
394
                    }
395 396 397 398
                  }
                }
              }
            }
399
          }
400 401
        }
      }
402

403 404
      //Table 5.2.2.2.1-8:
      //Codebook for 4-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS
405
      if(max_mimo_layers>=4) {
sfn's avatar
sfn committed
406
        //pmi_size is computed as follows
407
        gNB->pmiq_size[3] = 1;//unity matrix
sfn's avatar
sfn committed
408 409 410 411 412
        for(int llb=0; llb<N1*O1; llb++) { //i_1_1
          for (int mmb=0; mmb<N2*O2; mmb++) { //i_1_2
            for(int ll=0; ll<N1*O1; ll++) { //i_1_1
              for (int mm=0; mm<N2*O2; mm++) { //i_1_2
                for (int nn=0; nn<2; nn++) {
413
                  if((llb != ll) || (mmb != mm)) gNB->pmiq_size[3] += 1;
sfn's avatar
sfn committed
414 415 416 417 418
                }
              }
            }
          }
        }
419

420
        mat[3] = (int32_t **)malloc16(gNB->pmiq_size[3]*sizeof(int32_t *));
421 422 423 424 425
        //pmi=0 corresponds to unit matrix
        mat[3][0] = (int32_t *)calloc((2*N1*N2)*(4),sizeof(int32_t));
        for(int j_col=0; j_col<4; j_col++) { //4 layers
          for (int i_rows=0; i_rows<2*N1*N2; i_rows++) { //2-x polarized antenna
            if(j_col==i_rows) {
sfn's avatar
sfn committed
426
              mat[3][0][i_rows*4+j_col] = 0x7fff;
427
            }
428 429
          }
        }
430

sfn's avatar
sfn committed
431
        pmiq = 0;
432 433 434 435 436 437
        //pmi=1,...,pmi_size are computed as follows
        for(int llb=0; llb<N1*O1; llb++) { //i_1_1
          for (int mmb=0; mmb<N2*O2; mmb++) { //i_1_2
            for(int ll=0; ll<N1*O1; ll++) { //i_1_1
              for (int mm=0; mm<N2*O2; mm++) { //i_1_2
                for (int nn=0; nn<2; nn++) {
438

sfn's avatar
sfn committed
439 440 441
                  if((llb != ll) || (mmb != mm)){
                    pmiq += 1;
                    mat[3][pmiq] = (int32_t *)malloc16((2*N1*N2)*4*sizeof(int32_t));
442
                    LOG_D(PHY, "layer 4 pmiq = %d\n",pmiq);
sfn's avatar
sfn committed
443 444 445 446 447 448 449 450 451 452 453
                    for(int j_col=0; j_col<4; j_col++) {
                      if (j_col==0) {
                        llc = llb;
                        mmc = mmb;
                        phase_sign = 1;
                      }
                      if (j_col==1) {
                        llc = ll;
                        mmc = mm;
                        phase_sign = 1;
                      }
sfn's avatar
sfn committed
454
                      if (j_col==2) {
sfn's avatar
sfn committed
455 456 457 458
                        llc = llb;
                        mmc = mmb;
                        phase_sign = -1;
                      }
sfn's avatar
sfn committed
459
                      if (j_col==3) {
sfn's avatar
sfn committed
460 461 462 463 464 465 466 467 468 469 470 471 472 473
                        llc = ll;
                        mmc = mm;
                        phase_sign = -1;
                      }
                      for (int i_rows=0; i_rows<N1*N2; i_rows++) {
                        res_code=sqrt(1/(double)(4*CSI_RS_antenna_ports))*v_lm[llc][mmc][i_rows];
                        if (creal(res_code)>0)
                          ((short*) &mat[3][pmiq][i_rows*4+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
                        else
                          ((short*) &mat[3][pmiq][i_rows*4+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
                        if (cimag(res_code)>0)
                          ((short*) &mat[3][pmiq][i_rows*4+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
                        else
                          ((short*) &mat[3][pmiq][i_rows*4+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
474 475
                        LOG_D(PHY, "4 Layer Precoding Matrix[3][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
                              pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[3][pmiq][i_rows*4+j_col])[0],((short*) &mat[3][pmiq][i_rows*4+j_col])[1]);
sfn's avatar
sfn committed
476 477 478 479 480 481 482 483 484 485 486 487
                      }

                      for (int i_rows=N1*N2; i_rows<2*N1*N2; i_rows++) {
                        res_code=sqrt(1/(double)(4*CSI_RS_antenna_ports))*(phase_sign)*theta_n[nn]*v_lm[llc][mmc][i_rows-N1*N2];
                        if (creal(res_code)>0)
                          ((short*) &mat[3][pmiq][i_rows*4+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
                        else
                          ((short*) &mat[3][pmiq][i_rows*4+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
                        if (cimag(res_code)>0)
                          ((short*) &mat[3][pmiq][i_rows*4+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
                        else
                          ((short*) &mat[3][pmiq][i_rows*4+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
488 489
                        LOG_D(PHY, "4 Layer Precoding Matrix[3][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
                              pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[3][pmiq][i_rows*4+j_col])[0],((short*) &mat[3][pmiq][i_rows*4+j_col])[1]);
sfn's avatar
sfn committed
490
                      }
491
                    }
492 493 494 495
                  }
                }
              }
            }
496 497
          }
        }
498 499 500
      }
    }
  }
501
  return 0;
502
}
503

504 505
int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
{
506
  // shortcuts
507
  NR_DL_FRAME_PARMS *const fp       = &gNB->frame_parms;
508
  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
509
  NR_gNB_COMMON *const common_vars  = &gNB->common_vars;
510
  NR_gNB_PRACH *const prach_vars   = &gNB->prach_vars;
511

512
  int i;
513 514
  int Ptx=cfg->carrier_config.num_tx_ant.value;
  int Prx=cfg->carrier_config.num_rx_ant.value;
515
  int max_ul_mimo_layers = 4;
516

517 518
  AssertFatal(Ptx>0 && Ptx<9,"Ptx %d is not supported\n",Ptx);
  AssertFatal(Prx>0 && Prx<9,"Prx %d is not supported\n",Prx);
519
  LOG_I(PHY,"[gNB %d] %s() About to wait for gNB to be configured\n", gNB->Mod_id, __FUNCTION__);
520

521
  while(gNB->configured == 0) usleep(10000);
522

frtabu's avatar
frtabu committed
523
  load_dftslib();
cig's avatar
cig committed
524

525
  crcTableInit();
526 527
  init_scrambling_luts();
  init_pucch2_luts();
528

529 530
  nr_init_fde(); // Init array for frequency equalization of transform precoding of PUSCH

531
  load_nrLDPClib(NULL);
532

533 534
  gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB;

535
  init_codebook_gNB(gNB);
536
  init_delay_table(fp->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, fp->delay_table);
537

Guy De Souza's avatar
Guy De Souza committed
538
  // PBCH DMRS gold sequences generation
Guy De Souza's avatar
Guy De Souza committed
539
  nr_init_pbch_dmrs(gNB);
540
  //PDCCH DMRS init
541
  gNB->nr_gold_pdcch_dmrs = (uint32_t ***)malloc16(fp->slots_per_frame*sizeof(uint32_t **));
Guy De Souza's avatar
Guy De Souza committed
542
  uint32_t ***pdcch_dmrs             = gNB->nr_gold_pdcch_dmrs;
Guy De Souza's avatar
Guy De Souza committed
543
  AssertFatal(pdcch_dmrs!=NULL, "NR init: pdcch_dmrs malloc failed\n");
544

545
  gNB->bad_pucch = 0;
546 547
  if (gNB->TX_AMP == 0)
    gNB->TX_AMP = AMP;
548 549 550
  // ceil(((NB_RB<<1)*3)/32) // 3 RE *2(QPSK)
  int pdcch_dmrs_init_length =  (((fp->N_RB_DL<<1)*3)>>5)+1;

Guy De Souza's avatar
Guy De Souza committed
551
  for (int slot=0; slot<fp->slots_per_frame; slot++) {
552
    pdcch_dmrs[slot] = (uint32_t **)malloc16(fp->symbols_per_slot*sizeof(uint32_t *));
Guy De Souza's avatar
Guy De Souza committed
553
    AssertFatal(pdcch_dmrs[slot]!=NULL, "NR init: pdcch_dmrs for slot %d - malloc failed\n", slot);
554 555

    for (int symb=0; symb<fp->symbols_per_slot; symb++) {
556
      pdcch_dmrs[slot][symb] = (uint32_t *)malloc16(pdcch_dmrs_init_length*sizeof(uint32_t));
rmagueta's avatar
rmagueta committed
557
      LOG_D(PHY,"pdcch_dmrs[%d][%d] %p\n",slot,symb,pdcch_dmrs[slot][symb]);
Guy De Souza's avatar
Guy De Souza committed
558 559
      AssertFatal(pdcch_dmrs[slot][symb]!=NULL, "NR init: pdcch_dmrs for slot %d symbol %d - malloc failed\n", slot, symb);
    }
Guy De Souza's avatar
Guy De Souza committed
560
  }
561

562
  nr_generate_modulation_table();
563
  gNB->pdcch_gold_init = cfg->cell_config.phy_cell_id.value;
564
  nr_init_pdcch_dmrs(gNB, cfg->cell_config.phy_cell_id.value);
Guy De Souza's avatar
Guy De Souza committed
565
  nr_init_pbch_interleaver(gNB->nr_pbch_interleaver);
566

567 568 569
  //PDSCH DMRS init
  gNB->nr_gold_pdsch_dmrs = (uint32_t ****)malloc16(fp->slots_per_frame*sizeof(uint32_t ***));
  uint32_t ****pdsch_dmrs             = gNB->nr_gold_pdsch_dmrs;
Guy De Souza's avatar
Guy De Souza committed
570

571 572
  // ceil(((NB_RB*12(k)*2(QPSK)/32) // 3 RE *2(QPSK)
  const int pdsch_dmrs_init_length =  ((fp->N_RB_DL*24)>>5)+1;
573 574
  for (int slot=0; slot<fp->slots_per_frame; slot++) {
    pdsch_dmrs[slot] = (uint32_t ***)malloc16(fp->symbols_per_slot*sizeof(uint32_t **));
ISIP CS/NCTU's avatar
ISIP CS/NCTU committed
575
    AssertFatal(pdsch_dmrs[slot]!=NULL, "NR init: pdsch_dmrs for slot %d - malloc failed\n", slot);
576 577

    for (int symb=0; symb<fp->symbols_per_slot; symb++) {
578
      pdsch_dmrs[slot][symb] = (uint32_t **)malloc16(NR_NB_NSCID*sizeof(uint32_t *));
ISIP CS/NCTU's avatar
ISIP CS/NCTU committed
579
      AssertFatal(pdsch_dmrs[slot][symb]!=NULL, "NR init: pdsch_dmrs for slot %d symbol %d - malloc failed\n", slot, symb);
580

581
      for (int q=0; q<NR_NB_NSCID; q++) {
582
        pdsch_dmrs[slot][symb][q] = (uint32_t *)malloc16(pdsch_dmrs_init_length*sizeof(uint32_t));
583
        AssertFatal(pdsch_dmrs[slot][symb][q]!=NULL, "NR init: pdsch_dmrs for slot %d symbol %d nscid %d - malloc failed\n", slot, symb, q);
Guy De Souza's avatar
Guy De Souza committed
584
      }
ISIP CS/NCTU's avatar
ISIP CS/NCTU committed
585 586
    }
  }
587

588

589
  for (int nscid = 0; nscid < NR_NB_NSCID; nscid++) {
590 591 592
    gNB->pdsch_gold_init[nscid] = cfg->cell_config.phy_cell_id.value;
    nr_init_pdsch_dmrs(gNB, nscid, cfg->cell_config.phy_cell_id.value);
  }
593

594
  //PUSCH DMRS init
595
  gNB->nr_gold_pusch_dmrs = (uint32_t ****)malloc16(NR_NB_NSCID*sizeof(uint32_t ***));
596

597
  uint32_t ****pusch_dmrs = gNB->nr_gold_pusch_dmrs;
598

599
  int pusch_dmrs_init_length =  ((fp->N_RB_UL*12)>>5)+1;
600
  for(int nscid=0; nscid<NR_NB_NSCID; nscid++) {
601 602 603 604 605 606
    pusch_dmrs[nscid] = (uint32_t ***)malloc16(fp->slots_per_frame*sizeof(uint32_t **));
    AssertFatal(pusch_dmrs[nscid]!=NULL, "NR init: pusch_dmrs for nscid %d - malloc failed\n", nscid);

    for (int slot=0; slot<fp->slots_per_frame; slot++) {
      pusch_dmrs[nscid][slot] = (uint32_t **)malloc16(fp->symbols_per_slot*sizeof(uint32_t *));
      AssertFatal(pusch_dmrs[nscid][slot]!=NULL, "NR init: pusch_dmrs for slot %d - malloc failed\n", slot);
607

608
      for (int symb=0; symb<fp->symbols_per_slot; symb++) {
609
        pusch_dmrs[nscid][slot][symb] = (uint32_t *)malloc16(pusch_dmrs_init_length*sizeof(uint32_t));
610 611 612
        AssertFatal(pusch_dmrs[nscid][slot][symb]!=NULL, "NR init: pusch_dmrs for slot %d symbol %d - malloc failed\n", slot, symb);
      }
    }
613 614
  }

615
  for (int nscid=0; nscid<NR_NB_NSCID; nscid++) {
616 617 618
    gNB->pusch_gold_init[nscid] = cfg->cell_config.phy_cell_id.value;
    nr_gold_pusch(gNB, nscid, gNB->pusch_gold_init[nscid]);
  }
619

620
  // CSI RS init
621 622
  // ceil((NB_RB*8(max allocation per RB)*2(QPSK))/32)
  int csi_dmrs_init_length =  ((fp->N_RB_DL<<4)>>5)+1;
623 624 625
  gNB->nr_csi_info = (nr_csi_info_t *)malloc16_clear(sizeof(nr_csi_info_t));
  gNB->nr_csi_info->nr_gold_csi_rs = (uint32_t ***)malloc16(fp->slots_per_frame * sizeof(uint32_t **));
  AssertFatal(gNB->nr_csi_info->nr_gold_csi_rs != NULL, "NR init: csi reference signal malloc failed\n");
626
  for (int slot=0; slot<fp->slots_per_frame; slot++) {
627 628
    gNB->nr_csi_info->nr_gold_csi_rs[slot] = (uint32_t **)malloc16(fp->symbols_per_slot * sizeof(uint32_t *));
    AssertFatal(gNB->nr_csi_info->nr_gold_csi_rs[slot] != NULL, "NR init: csi reference signal for slot %d - malloc failed\n", slot);
629
    for (int symb=0; symb<fp->symbols_per_slot; symb++) {
630 631
      gNB->nr_csi_info->nr_gold_csi_rs[slot][symb] = (uint32_t *)malloc16(csi_dmrs_init_length * sizeof(uint32_t));
      AssertFatal(gNB->nr_csi_info->nr_gold_csi_rs[slot][symb] != NULL, "NR init: csi reference signal for slot %d symbol %d - malloc failed\n", slot, symb);
632 633 634
    }
  }

635 636
  gNB->nr_csi_info->csi_gold_init = cfg->cell_config.phy_cell_id.value;
  nr_init_csi_rs(&gNB->frame_parms, gNB->nr_csi_info->nr_gold_csi_rs, cfg->cell_config.phy_cell_id.value);
637

638
  //PRS init
Mohsen Ahadi's avatar
Mohsen Ahadi committed
639
  nr_init_prs(gNB);
ahadi's avatar
ahadi committed
640

rmagueta's avatar
rmagueta committed
641 642
  generate_ul_reference_signal_sequences(SHRT_MAX);

dir's avatar
dir committed
643 644
  /* Generate low PAPR type 1 sequences for PUSCH DMRS, these are used if transform precoding is enabled.  */
  generate_lowpapr_typ1_refsig_sequences(SHRT_MAX);
645

Guy De Souza's avatar
Guy De Souza committed
646 647
  /// Transport init necessary for NR synchro
  init_nr_transport(gNB);
648

649 650 651 652 653 654 655 656 657
  gNB->nr_srs_info = (nr_srs_info_t **)malloc16_clear(gNB->max_nb_srs * sizeof(nr_srs_info_t*));
  for (int id = 0; id < gNB->max_nb_srs; id++) {
    gNB->nr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t));
    gNB->nr_srs_info[id]->srs_generated_signal = (int32_t**)malloc16_clear(MAX_NUM_NR_SRS_AP*sizeof(int32_t*));
    for(int ap=0; ap<MAX_NUM_NR_SRS_AP; ap++) {
      gNB->nr_srs_info[id]->srs_generated_signal[ap] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
    }
  }

658 659
  common_vars->txdataF = (c16_t **)malloc16(Ptx*sizeof(c16_t*));
  common_vars->rxdataF = (c16_t **)malloc16(Prx*sizeof(c16_t*));
660 661
  /* Do NOT allocate per-antenna txdataF/rxdataF: the gNB gets a pointer to the
   * RU to copy/recover freq-domain memory from there */
662
  common_vars->beam_id = (uint8_t **)malloc16(Ptx*sizeof(uint8_t*));
663

664
  for (i=0;i<Ptx;i++){
665
    common_vars->txdataF[i] = (c16_t*)malloc16_clear(fp->samples_per_frame_wCP*sizeof(c16_t)); // [hna] samples_per_frame without CP
666 667
    LOG_D(PHY,"[INIT] common_vars->txdataF[%d] = %p (%lu bytes)\n",
          i,common_vars->txdataF[i],
668
          fp->samples_per_frame_wCP*sizeof(c16_t));
669 670
    common_vars->beam_id[i] = (uint8_t*)malloc16_clear(fp->symbols_per_slot*fp->slots_per_frame*sizeof(uint8_t));
    memset(common_vars->beam_id[i],255,fp->symbols_per_slot*fp->slots_per_frame);
671
  }
672 673
  common_vars->debugBuff = (int32_t*)malloc16_clear(fp->samples_per_frame*sizeof(int32_t)*100);	
  common_vars->debugBuff_sample_offset = 0; 
674

675
  // PRACH
676
  prach_vars->prachF = (int16_t *)malloc16_clear( 1024*2*sizeof(int16_t) );
677
  prach_vars->rxsigF = (int16_t **)malloc16_clear(Prx*sizeof(int16_t*));
678
  prach_vars->prach_ifft       = (int32_t *)malloc16_clear(1024*2*sizeof(int32_t));
679

680 681
  init_prach_list(gNB);

682
  int N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value;
683
  int n_buf = Prx*max_ul_mimo_layers;
684

685
  int nb_re_pusch = N_RB_UL * NR_NB_SC_PER_RB;
686
  int nb_re_pusch2 = (nb_re_pusch + 15) & ~15;
687

francescomani's avatar
francescomani committed
688
  gNB->pusch_vars = (NR_gNB_PUSCH *)malloc16_clear(gNB->max_nb_pusch * sizeof(NR_gNB_PUSCH));
689
  for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
francescomani's avatar
francescomani committed
690 691 692 693 694 695 696 697
    NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id];
    pusch->rxdataF_ext = (int32_t **)malloc16(Prx * sizeof(int32_t *));
    pusch->ul_ch_estimates = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
    pusch->ul_ch_estimates_ext = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
    pusch->ptrs_phase_per_slot = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
    pusch->ul_ch_estimates_time = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
    pusch->rxdataF_comp = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
    pusch->llr_layers = (int16_t **)malloc16(max_ul_mimo_layers * sizeof(int32_t *));
698
    for (i = 0; i < Prx; i++) {
francescomani's avatar
francescomani committed
699
      pusch->rxdataF_ext[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot);
700
    }
701
    for (i = 0; i < n_buf; i++) {
francescomani's avatar
francescomani committed
702 703 704 705 706
      pusch->ul_ch_estimates[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->ofdm_symbol_size * fp->symbols_per_slot);
      pusch->ul_ch_estimates_ext[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot);
      pusch->ul_ch_estimates_time[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->ofdm_symbol_size);
      pusch->ptrs_phase_per_slot[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->symbols_per_slot); // symbols per slot
      pusch->rxdataF_comp[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot);
707 708 709
    }

    for (i=0; i< max_ul_mimo_layers; i++) {
francescomani's avatar
francescomani committed
710 711
      pusch->llr_layers[i] = (int16_t *)malloc16_clear((8 * ((3 * 8 * 6144) + 12))
                                                       * sizeof(int16_t)); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear
712
    }
francescomani's avatar
francescomani committed
713 714 715 716
    pusch->llr = (int16_t *)malloc16_clear((8 * ((3 * 8 * 6144) + 12))
                                           * sizeof(int16_t)); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear
    pusch->ul_valid_re_per_slot = (int16_t *)malloc16_clear(sizeof(int16_t) * fp->symbols_per_slot);
  } // ulsch_id
717

718 719 720
  return (0);
}

721 722
void phy_free_nr_gNB(PHY_VARS_gNB *gNB)
{
723
  NR_DL_FRAME_PARMS* const fp       = &gNB->frame_parms;
724 725 726 727
  const int Ptx = gNB->gNB_config.carrier_config.num_tx_ant.value;
  const int Prx = gNB->gNB_config.carrier_config.num_rx_ant.value;
  const int max_ul_mimo_layers = 4; // taken from phy_init_nr_gNB()
  const int n_buf = Prx * max_ul_mimo_layers;
laurent's avatar
laurent committed
728 729 730
  PHY_MEASUREMENTS_gNB *meas=&gNB->measurements;
  free_and_zero(meas->n0_subband_power);
  free_and_zero(meas->n0_subband_power_dB);
731
  int max_dl_mimo_layers =(fp->nb_antennas_tx<NR_MAX_NB_LAYERS) ? fp->nb_antennas_tx : NR_MAX_NB_LAYERS;
732 733 734 735 736
  if (fp->nb_antennas_tx>1) {
    for (int nl = 0; nl < max_dl_mimo_layers; nl++) {
      for(int size = 0; size < gNB->pmiq_size[nl]; size++)
        free_and_zero(gNB->nr_mimo_precoding_matrix[nl][size]);
      free_and_zero(gNB->nr_mimo_precoding_matrix[nl]);
737
    }
738
    free_and_zero(gNB->nr_mimo_precoding_matrix);
739
  }
740

741 742 743 744 745 746 747 748 749 750 751
  uint32_t ***pdcch_dmrs = gNB->nr_gold_pdcch_dmrs;
  for (int slot = 0; slot < fp->slots_per_frame; slot++) {
    for (int symb = 0; symb < fp->symbols_per_slot; symb++)
      free_and_zero(pdcch_dmrs[slot][symb]);
    free_and_zero(pdcch_dmrs[slot]);
  }
  free_and_zero(pdcch_dmrs);

  uint32_t ****pdsch_dmrs = gNB->nr_gold_pdsch_dmrs;
  for (int slot = 0; slot < fp->slots_per_frame; slot++) {
    for (int symb = 0; symb < fp->symbols_per_slot; symb++) {
752
      for (int q = 0; q < NR_NB_NSCID; q++)
753 754 755 756 757 758
        free_and_zero(pdsch_dmrs[slot][symb][q]);
      free_and_zero(pdsch_dmrs[slot][symb]);
    }
    free_and_zero(pdsch_dmrs[slot]);
  }
  free_and_zero(gNB->nr_gold_pdsch_dmrs);
759

760 761 762 763 764 765 766 767 768 769 770
  uint32_t ****pusch_dmrs = gNB->nr_gold_pusch_dmrs;
  for(int nscid = 0; nscid < 2; nscid++) {
    for (int slot = 0; slot < fp->slots_per_frame; slot++) {
      for (int symb = 0; symb < fp->symbols_per_slot; symb++)
        free_and_zero(pusch_dmrs[nscid][slot][symb]);
      free_and_zero(pusch_dmrs[nscid][slot]);
    }
    free_and_zero(pusch_dmrs[nscid]);
  }
  free_and_zero(pusch_dmrs);

771
  uint32_t ***nr_gold_csi_rs = gNB->nr_csi_info->nr_gold_csi_rs;
772 773
  for (int slot = 0; slot < fp->slots_per_frame; slot++) {
    for (int symb = 0; symb < fp->symbols_per_slot; symb++)
774 775
      free_and_zero(nr_gold_csi_rs[slot][symb]);
    free_and_zero(nr_gold_csi_rs[slot]);
776
  }
777 778
  free_and_zero(nr_gold_csi_rs);
  free_and_zero(gNB->nr_csi_info);
779

780
  for (int id = 0; id < gNB->max_nb_srs; id++) {
Roberto Louro Magueta's avatar
Roberto Louro Magueta committed
781 782
    for(int i=0; i<MAX_NUM_NR_SRS_AP; i++) {
      free_and_zero(gNB->nr_srs_info[id]->srs_generated_signal[i]);
783
    }
Roberto Louro Magueta's avatar
Roberto Louro Magueta committed
784
    free_and_zero(gNB->nr_srs_info[id]->srs_generated_signal);
785 786
    free_and_zero(gNB->nr_srs_info[id]);
  }
francescomani's avatar
francescomani committed
787
  free_and_zero(gNB->nr_srs_info);
788

789 790 791 792 793 794
  free_ul_reference_signal_sequences();
  free_gnb_lowpapr_sequences();

  reset_nr_transport(gNB);

  NR_gNB_COMMON * common_vars = &gNB->common_vars;
795
  for (int i = 0; i < Ptx; i++) {
796
    free_and_zero(common_vars->txdataF[i]);
797 798 799
    free_and_zero(common_vars->beam_id[i]);
  }

800 801 802 803 804 805 806 807 808 809 810
  for (int rsc=0; rsc < gNB->prs_vars.NumPRSResources; rsc++) {
    for (int slot=0; slot<fp->slots_per_frame; slot++) {
      for (int symb=0; symb<fp->symbols_per_slot; symb++) {
        free_and_zero(gNB->nr_gold_prs[rsc][slot][symb]);
      }
      free_and_zero(gNB->nr_gold_prs[rsc][slot]);
    }
    free_and_zero(gNB->nr_gold_prs[rsc]);
  }
  free_and_zero(gNB->nr_gold_prs);

811 812
  /* Do NOT free per-antenna txdataF/rxdataF: the gNB gets a pointer to the
   * RU's txdataF/rxdataF, and the RU will free that */
813 814
  free_and_zero(common_vars->txdataF);
  free_and_zero(common_vars->rxdataF);
815
  free_and_zero(common_vars->beam_id);
816

817
  free_and_zero(common_vars->debugBuff);
818

819
  NR_gNB_PRACH* prach_vars = &gNB->prach_vars;
820
  free_and_zero(prach_vars->prachF);
821 822
  free_and_zero(prach_vars->rxsigF);
  free_and_zero(prach_vars->prach_ifft);
823

824
  for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
francescomani's avatar
francescomani committed
825
    NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id];
826
    for (int i=0; i< max_ul_mimo_layers; i++)
francescomani's avatar
francescomani committed
827
      free_and_zero(pusch_vars->llr_layers[i]);
828
    for (int i = 0; i < Prx; i++) {
francescomani's avatar
francescomani committed
829
      free_and_zero(pusch_vars->rxdataF_ext[i]);
830
    }
831
    for (int i = 0; i < n_buf; i++) {
francescomani's avatar
francescomani committed
832 833 834 835 836
      free_and_zero(pusch_vars->ul_ch_estimates[i]);
      free_and_zero(pusch_vars->ul_ch_estimates_ext[i]);
      free_and_zero(pusch_vars->ul_ch_estimates_time[i]);
      free_and_zero(pusch_vars->ptrs_phase_per_slot[i]);
      free_and_zero(pusch_vars->rxdataF_comp[i]);
837
    }
francescomani's avatar
francescomani committed
838 839 840 841 842 843 844 845 846 847 848
    free_and_zero(pusch_vars->llr_layers);
    free_and_zero(pusch_vars->rxdataF_ext);
    free_and_zero(pusch_vars->ul_ch_estimates);
    free_and_zero(pusch_vars->ul_ch_estimates_ext);
    free_and_zero(pusch_vars->ptrs_phase_per_slot);
    free_and_zero(pusch_vars->ul_ch_estimates_time);
    free_and_zero(pusch_vars->ul_valid_re_per_slot);
    free_and_zero(pusch_vars->rxdataF_comp);

    free_and_zero(pusch_vars->llr);
  } // ULSCH_id
849
  free(gNB->pusch_vars);
850
}
MaheshK1995's avatar
MaheshK1995 committed
851 852 853 854 855 856 857

//Adding nr_schedule_handler
void install_nr_schedule_handlers(NR_IF_Module_t *if_inst)
{
  if_inst->NR_PHY_config_req = nr_phy_config_request;
  if_inst->NR_Schedule_response = nr_schedule_response;
}
Guy De Souza's avatar
Guy De Souza committed
858
/*
859 860 861 862
void install_schedule_handlers(IF_Module_t *if_inst)
{
  if_inst->PHY_config_req = phy_config_request;
  if_inst->schedule_response = schedule_response;
Guy De Souza's avatar
Guy De Souza committed
863
}*/
Guy De Souza's avatar
Guy De Souza committed
864 865

/// this function is a temporary addition for NR configuration
866

867

868 869 870 871 872 873 874 875
void nr_phy_config_request_sim(PHY_VARS_gNB *gNB,
                               int N_RB_DL,
                               int N_RB_UL,
                               int mu,
                               int Nid_cell,
                               uint64_t position_in_burst)
{
  NR_DL_FRAME_PARMS *fp                                   = &gNB->frame_parms;
876
  nfapi_nr_config_request_scf_t *gNB_config               = &gNB->gNB_config;
Guy De Souza's avatar
Guy De Souza committed
877
  //overwrite for new NR parameters
878

879 880 881 882
  uint64_t rev_burst=0;
  for (int i=0; i<64; i++)
    rev_burst |= (((position_in_burst>>(63-i))&0x01)<<i);

883 884 885
  gNB_config->cell_config.phy_cell_id.value             = Nid_cell;
  gNB_config->ssb_config.scs_common.value               = mu;
  gNB_config->ssb_table.ssb_subcarrier_offset.value     = 0;
Francesco Mani's avatar
Francesco Mani committed
886
  gNB_config->ssb_table.ssb_offset_point_a.value        = (N_RB_DL-20)>>1;
887 888
  gNB_config->ssb_table.ssb_mask_list[1].ssb_mask.value = (rev_burst)&(0xFFFFFFFF);
  gNB_config->ssb_table.ssb_mask_list[0].ssb_mask.value = (rev_burst>>32)&(0xFFFFFFFF);
889 890 891 892
  gNB_config->cell_config.frame_duplex_type.value       = TDD;
  gNB_config->ssb_table.ssb_period.value		= 1; //10ms
  gNB_config->carrier_config.dl_grid_size[mu].value     = N_RB_DL;
  gNB_config->carrier_config.ul_grid_size[mu].value     = N_RB_UL;
893 894
  gNB_config->carrier_config.num_tx_ant.value           = fp->nb_antennas_tx;
  gNB_config->carrier_config.num_rx_ant.value           = fp->nb_antennas_rx;
895

896
  gNB_config->tdd_table.tdd_period.value = 0;
897
  //gNB_config->subframe_config.dl_cyclic_prefix_type.value = (fp->Ncp == NORMAL) ? NFAPI_CP_NORMAL : NFAPI_CP_EXTENDED;
898

899 900 901 902 903 904
  if (mu==0) {
    fp->dl_CarrierFreq = 2600000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value);
    fp->ul_CarrierFreq = 2600000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000);
    fp->nr_band = 38;
    //  fp->threequarter_fs= 0;
  } else if (mu==1) {
905 906
    fp->dl_CarrierFreq = 3600000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value);
    fp->ul_CarrierFreq = 3600000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000);
907 908 909 910 911 912 913 914
    fp->nr_band = 78;
    //  fp->threequarter_fs= 0;
  } else if (mu==3) {
    fp->dl_CarrierFreq = 27524520000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value);
    fp->ul_CarrierFreq = 27524520000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000);
    fp->nr_band = 261;
    //  fp->threequarter_fs= 0;
  }
915 916

  fp->threequarter_fs = 0;
917 918
  int bw_index = get_supported_band_index(mu, fp->nr_band, N_RB_DL);
  gNB_config->carrier_config.dl_bandwidth.value = get_supported_bw_mhz(fp->nr_band > 256 ? FR2 : FR1, bw_index);
919

Guy De Souza's avatar
Guy De Souza committed
920
  nr_init_frame_parms(gNB_config, fp);
921

922
  fp->ofdm_offset_divisor = UINT_MAX;
923 924 925
  init_symbol_rotation(fp);
  init_timeshift_rotation(fp);

926
  gNB->configured    = 1;
Guy De Souza's avatar
Guy De Souza committed
927
  LOG_I(PHY,"gNB configured\n");
928
}
929

930 931
void nr_phy_config_request(NR_PHY_Config_t *phy_config)
{
932
  uint8_t Mod_id = phy_config->Mod_id;
933
  uint8_t short_sequence, num_sequences, rootSequenceIndex, fd_occasion;
934 935 936
  NR_DL_FRAME_PARMS *fp = &RC.gNB[Mod_id]->frame_parms;
  nfapi_nr_config_request_scf_t *gNB_config = &RC.gNB[Mod_id]->gNB_config;

Raymond Knopp's avatar
Raymond Knopp committed
937
  memcpy((void*)gNB_config,phy_config->cfg,sizeof(*phy_config->cfg));
938 939 940

  uint64_t dl_bw_khz = (12*gNB_config->carrier_config.dl_grid_size[gNB_config->ssb_config.scs_common.value].value)*(15<<gNB_config->ssb_config.scs_common.value);
  fp->dl_CarrierFreq = ((dl_bw_khz>>1) + gNB_config->carrier_config.dl_frequency.value)*1000 ;
941
  
942 943
  uint64_t ul_bw_khz = (12*gNB_config->carrier_config.ul_grid_size[gNB_config->ssb_config.scs_common.value].value)*(15<<gNB_config->ssb_config.scs_common.value);
  fp->ul_CarrierFreq = ((ul_bw_khz>>1) + gNB_config->carrier_config.uplink_frequency.value)*1000 ;
Raymond Knopp's avatar
Raymond Knopp committed
944

945 946
  int32_t dlul_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq;
  fp->nr_band = get_band(fp->dl_CarrierFreq, dlul_offset);
947 948 949

  LOG_I(PHY, "DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, dlul_offset);

950
  fp->threequarter_fs = openair0_cfg[0].threequarter_fs;
951
  LOG_A(PHY,"Configuring MIB for instance %d, : (Nid_cell %d,DL freq %llu, UL freq %llu)\n",
952
        Mod_id,
953
        gNB_config->cell_config.phy_cell_id.value,
Raymond Knopp's avatar
Raymond Knopp committed
954 955
        (unsigned long long)fp->dl_CarrierFreq,
        (unsigned long long)fp->ul_CarrierFreq);
956

957
  nr_init_frame_parms(gNB_config, fp);
Rakesh's avatar
Rakesh committed
958
  
959

960
  if (RC.gNB[Mod_id]->configured == 1) {
961 962 963 964
    LOG_E(PHY,"Already gNB already configured, do nothing\n");
    return;
  }

965 966 967
  fd_occasion = 0;
  nfapi_nr_prach_config_t *prach_config = &gNB_config->prach_config;
  short_sequence = prach_config->prach_sequence_length.value;
968
//  for(fd_occasion = 0; fd_occasion <= prach_config->num_prach_fd_occasions.value ; fd_occasion) { // TODO Need to handle for msg1-fdm > 1
969 970 971 972
  num_sequences = prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value;
  rootSequenceIndex = prach_config->num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index.value;

  compute_nr_prach_seq(short_sequence, num_sequences, rootSequenceIndex, RC.gNB[Mod_id]->X_u);
973
//  }
974
  RC.gNB[Mod_id]->configured     = 1;
975

976
  fp->ofdm_offset_divisor = RC.gNB[Mod_id]->ofdm_offset_divisor;
977
  init_symbol_rotation(fp);
978
  init_timeshift_rotation(fp);
979

980
  LOG_I(PHY,"gNB %d configured\n",Mod_id);
Guy De Souza's avatar
Guy De Souza committed
981
}
982

983 984
void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg)
{
985 986
  NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
987
  uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value;
988
  msg->num_pdsch_slot = 0;
989

francescomani's avatar
francescomani committed
990
  msg->dlsch = malloc16(gNB->max_nb_pdsch * sizeof(NR_gNB_DLSCH_t *));
francescomani's avatar
francescomani committed
991
  int num_cw = NR_MAX_NB_LAYERS > 4? 2:1;
992
  for (int i = 0; i < gNB->max_nb_pdsch; i++) {
Robert Schmidt's avatar
Robert Schmidt committed
993
    LOG_D(PHY, "Allocating Transport Channel Buffers for DLSCH %d/%d\n", i, gNB->max_nb_pdsch);
francescomani's avatar
francescomani committed
994
    msg->dlsch[i] = (NR_gNB_DLSCH_t *)malloc16(num_cw * sizeof(NR_gNB_DLSCH_t));
995
    for (int j = 0; j < num_cw; j++) {
996
      msg->dlsch[i][j] = new_gNB_dlsch(fp, grid_size);
997 998 999
    }
  }
}
Mahesh's avatar
Mahesh committed
1000

1001 1002 1003 1004 1005
void reset_DLSCH_struct(const PHY_VARS_gNB *gNB, processingData_L1tx_t *msg)
{
  const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
  const nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
  const uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value;
francescomani's avatar
francescomani committed
1006
  int num_cw = NR_MAX_NB_LAYERS > 4? 2:1;
1007
  for (int i = 0; i < gNB->max_nb_pdsch; i++) {
francescomani's avatar
francescomani committed
1008
    for (int j = 0; j < num_cw; j++) {
1009
      free_gNB_dlsch(&msg->dlsch[i][j], grid_size, fp);
1010 1011 1012
    }
    free(msg->dlsch[i]);
  }
1013
  free(msg->dlsch);
1014 1015
}

1016 1017 1018
void init_nr_transport(PHY_VARS_gNB *gNB)
{

1019
  NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
1020
  const nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
1021 1022
  LOG_I(PHY, "Initialise nr transport\n");

1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
  int nb_slots_per_period = cfg->cell_config.frame_duplex_type.value ?
                            fp->slots_per_frame / get_nb_periods_per_frame(cfg->tdd_table.tdd_period.value) :
                            fp->slots_per_frame;
  int nb_ul_slots_period = 0;
  if (cfg->cell_config.frame_duplex_type.value) {
    for(int i=0; i<nb_slots_per_period; i++) {
      for(int j=0; j<NR_NUMBER_OF_SYMBOLS_PER_SLOT; j++) {
        if(cfg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[j].slot_config.value == 1) { // UL symbol
          nb_ul_slots_period++;
          break;
        }  
      }
    }
  }
  else
    nb_ul_slots_period = fp->slots_per_frame;

1040
  int buffer_ul_slots; // the UL channels are scheduled sl_ahead before they are transmitted
francescomani's avatar
francescomani committed
1041 1042 1043
  int slot_ahead = gNB->if_inst ? gNB->if_inst->sl_ahead : 6;
  if (slot_ahead > nb_slots_per_period)
    buffer_ul_slots = nb_ul_slots_period + (slot_ahead - nb_slots_per_period);
1044
  else
francescomani's avatar
francescomani committed
1045
    buffer_ul_slots = (nb_ul_slots_period < slot_ahead) ? nb_ul_slots_period : slot_ahead;
1046

1047 1048
  gNB->max_nb_pucch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1;
  gNB->max_nb_pusch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1;
1049
  gNB->max_nb_srs = buffer_ul_slots << 1; // assuming at most 2 SRS per slot
1050

francescomani's avatar
francescomani committed
1051
  gNB->pucch = (NR_gNB_PUCCH_t *)malloc16(gNB->max_nb_pucch * sizeof(NR_gNB_PUCCH_t));
1052
  for (int i = 0; i < gNB->max_nb_pucch; i++) {
francescomani's avatar
francescomani committed
1053
    memset(&gNB->pucch[i], 0, sizeof(gNB->pucch[i]));
Francesco Mani's avatar
Francesco Mani committed
1054 1055
  }

francescomani's avatar
francescomani committed
1056 1057 1058
  gNB->srs = (NR_gNB_SRS_t *)malloc16(gNB->max_nb_srs * sizeof(NR_gNB_SRS_t));
  for (int i = 0; i < gNB->max_nb_srs; i++)
    gNB->srs[i].active = 0;
1059

francescomani's avatar
francescomani committed
1060
  gNB->ulsch = (NR_gNB_ULSCH_t *)malloc16(gNB->max_nb_pusch * sizeof(NR_gNB_ULSCH_t));
1061
  for (int i = 0; i < gNB->max_nb_pusch; i++) {
Robert Schmidt's avatar
Robert Schmidt committed
1062
    LOG_D(PHY, "Allocating Transport Channel Buffers for ULSCH %d/%d\n", i, gNB->max_nb_pusch);
1063
    gNB->ulsch[i] = new_gNB_ulsch(gNB->max_ldpc_iterations, fp->N_RB_UL);
1064
  }
1065

1066
  gNB->rx_total_gain_dB=130;
1067

1068 1069
  //fp->pucch_config_common.deltaPUCCH_Shift = 1;
}
1070 1071 1072 1073 1074

void reset_nr_transport(PHY_VARS_gNB *gNB)
{
  const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;

francescomani's avatar
francescomani committed
1075 1076
  free(gNB->pucch);
  free(gNB->srs);
1077

1078
  for (int i = 0; i < gNB->max_nb_pusch; i++)
1079
    free_gNB_ulsch(&gNB->ulsch[i], fp->N_RB_UL);
Robert Schmidt's avatar
Robert Schmidt committed
1080
  free(gNB->ulsch);
1081
}