phy_procedures_nr_gNB.c 16 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
/*
 * 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 23
#include "PHY/phy_extern.h"
#include "PHY/defs_gNB.h"
Guy De Souza's avatar
Guy De Souza committed
24
#include "sched_nr.h"
Guy De Souza's avatar
Guy De Souza committed
25
#include "PHY/NR_TRANSPORT/nr_transport.h"
26
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
Guy De Souza's avatar
Guy De Souza committed
27
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
28
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
29
#include "PHY/NR_ESTIMATION/nr_ul_estimation.h"
30
#include "SCHED/sched_eNB.h"
31
#include "sched_nr.h"
32
#include "SCHED/sched_common_extern.h"
33 34 35
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h"
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h"
#include "fapi_nr_l1.h"
36 37
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
38
#include "PHY/INIT/phy_init.h"
39
#include "PHY/MODULATION/nr_modulation.h"
Guy De Souza's avatar
Guy De Souza committed
40 41 42 43 44 45 46 47
#include "T.h"

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

#include <time.h>

#if defined(ENABLE_ITTI)
48
  #include "intertask_interface.h"
Guy De Souza's avatar
Guy De Souza committed
49 50
#endif

Guy De Souza's avatar
Guy De Souza committed
51
extern uint8_t nfapi_mode;
52 53 54 55
/*
int return_ssb_type(nfapi_config_request_t *cfg)
{
  int mu = cfg->subframe_config.numerology_index_mu.value;
56
  nr_ssb_type_e ssb_type;
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

  switch(mu) {

  case NR_MU_0:
    ssb_type = nr_ssb_type_A;
    break;

  case NR_MU_1:
    ssb_type = nr_ssb_type_B;
    break;

  case NR_MU_3:
    ssb_type = nr_ssb_type_D;
    break;

  case NR_MU_4:
    ssb_type = nr_ssb_type_E;
    break;

  default:
    AssertFatal(0==1, "Invalid numerology index %d for the synchronization block\n", mu);
  }

  LOG_D(PHY, "SSB type %d\n", ssb_type);
  return ssb_type;

}*/

85

86

87
void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_t *cfg, NR_DL_FRAME_PARMS *fp) {
88 89
  fp->ssb_start_subcarrier = (12 * cfg->sch_config.n_ssb_crb.value + cfg->sch_config.ssb_subcarrier_offset.value)/(1<<cfg->subframe_config.numerology_index_mu.value);
  LOG_D(PHY, "SSB first subcarrier %d (%d,%d)\n", fp->ssb_start_subcarrier,cfg->sch_config.n_ssb_crb.value,cfg->sch_config.ssb_subcarrier_offset.value);
90
}
Guy De Souza's avatar
Guy De Souza committed
91

92
void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) {
Guy De Souza's avatar
Guy De Souza committed
93
  NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
94
  nfapi_nr_config_request_t *cfg = &gNB->gNB_config;
Guy De Souza's avatar
Guy De Souza committed
95 96
  int **txdataF = gNB->common_vars.txdataF;
  uint8_t *pbch_pdu=&gNB->pbch_pdu[0];
97
  uint8_t ssb_index, n_hf;
98
  int ssb_start_symbol, rel_slot;
99
  int txdataF_offset = (slot%2)*fp->samples_per_slot_wCP;
100
  uint16_t slots_per_hf = fp->slots_per_frame / 2;
Guy De Souza's avatar
Guy De Souza committed
101

102
  n_hf = cfg->sch_config.half_frame_index.value;
103 104 105

  // if SSB periodicity is 5ms, they are transmitted in both half frames
  if ( cfg->sch_config.ssb_periodicity.value == 5) {
106
    if (slot<slots_per_hf)
107 108 109 110 111
      n_hf=0;
    else
      n_hf=1;
  }

112
  // to set a effective slot number between 0 to 9 in the half frame where the SSB is supposed to be
113
  rel_slot = (n_hf)? (slot-slots_per_hf) : slot; 
114

115
  LOG_D(PHY,"common_signal_procedures: frame %d, slot %d\n",frame,slot);
Guy De Souza's avatar
Guy De Souza committed
116

117
  if(rel_slot<slots_per_hf && rel_slot>=0)  {
118 119
     for (int i=0; i<2; i++)  {  // max two SSB per frame
     
120
	ssb_index = i + 2*rel_slot; // computing the ssb_index
121 122
	if ((fp->L_ssb >> ssb_index) & 0x01)  { // generating the ssb only if the bit of L_ssb at current ssb index is 1
	
123
	  int ssb_start_symbol_abs = nr_get_ssb_start_symbol(fp, ssb_index, n_hf); // computing the starting symbol for current ssb
124 125
	  ssb_start_symbol = ssb_start_symbol_abs % 14;  // start symbol wrt slot

126
	  nr_set_ssb_first_subcarrier(cfg, fp);  // setting the first subcarrier
127
	  
128
	  // it is supposed that each logical antenna port correspont to a different beam so each SSB is stored into its own index of txdataF
129
    	  LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n",frame,slot, ssb_start_symbol);
130 131
    	  nr_generate_pss(gNB->d_pss, &txdataF[ssb_index][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
    	  nr_generate_sss(gNB->d_sss, &txdataF[ssb_index][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
132

133
	  if (fp->Lmax == 4)
134
	    nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],&txdataF[ssb_index][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
135
	  else
136
	    nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index],&txdataF[ssb_index][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
137 138

    	  nr_generate_pbch(&gNB->pbch,
Guy De Souza's avatar
Guy De Souza committed
139 140
                      pbch_pdu,
                      gNB->nr_pbch_interleaver,
141
                      &txdataF[ssb_index][txdataF_offset],
142
                      AMP,
Guy De Souza's avatar
Guy De Souza committed
143
                      ssb_start_symbol,
144
                      n_hf,fp->Lmax,ssb_index,
Guy De Souza's avatar
Guy De Souza committed
145
                      frame, cfg, fp);
146 147
	}
     }
148
  }
Guy De Souza's avatar
Guy De Souza committed
149 150 151
}

void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
152
                           int frame,int slot,
153
                           int do_meas) {
Guy De Souza's avatar
Guy De Souza committed
154
  int aa;
155
  uint8_t num_dci=0,num_pdsch_rnti;
Guy De Souza's avatar
Guy De Souza committed
156
  NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
157
  nfapi_nr_config_request_t *cfg = &gNB->gNB_config;
Guy De Souza's avatar
Guy De Souza committed
158
  int offset = gNB->CC_id;
159
  uint8_t ssb_frame_periodicity;  // every how many frames SSB are generated
160
  int txdataF_offset = (slot%2)*fp->samples_per_slot_wCP;
161 162 163 164 165

  if (cfg->sch_config.ssb_periodicity.value < 20)
    ssb_frame_periodicity = 1;
  else 
    ssb_frame_periodicity = (cfg->sch_config.ssb_periodicity.value)/10 ;  // 10ms is the frame length
Guy De Souza's avatar
Guy De Souza committed
166

167
  if ((cfg->subframe_config.duplex_mode.value == TDD) && (nr_slot_select(cfg,slot,frame)==SF_UL)) return;
Guy De Souza's avatar
Guy De Souza committed
168

169
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1);
170

171
  if (do_meas==1) start_meas(&gNB->phy_proc_tx);
Guy De Souza's avatar
Guy De Souza committed
172 173

  // clear the transmit data array for the current subframe
174
  for (aa=0; aa<fp->Lmax; aa++) {
175
    memset(&gNB->common_vars.txdataF[aa][txdataF_offset],0,fp->samples_per_slot_wCP*sizeof(int32_t));
Guy De Souza's avatar
Guy De Souza committed
176 177
  }

WANG Tsu-Han's avatar
WANG Tsu-Han committed
178
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_COMMON_TX,1);
179 180 181
  if (nfapi_mode == 0 || nfapi_mode == 1) { 
    if (!(frame%ssb_frame_periodicity))  // generate SSB only for given frames according to SSB periodicity
      nr_common_signal_procedures(gNB,frame, slot);
182
  }
WANG Tsu-Han's avatar
WANG Tsu-Han committed
183
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_COMMON_TX,0);
184 185

  num_dci = gNB->pdcch_vars.num_dci;
186
  num_pdsch_rnti = gNB->pdcch_vars.num_pdsch_rnti;
187

188
  for (int i=0; i<num_dci; i++) {
Raymond Knopp's avatar
Raymond Knopp committed
189
    LOG_D(PHY, "[gNB %d] Frame %d slot %d \
190
    Calling nr_generate_dci_top (number of DCI %d)\n", gNB->Mod_id, frame, slot, num_dci);
Guy De Souza's avatar
Guy De Souza committed
191

Raymond Knopp's avatar
Raymond Knopp committed
192
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
193

194
    nr_generate_dci_top(gNB->pdcch_vars.dci_alloc[i],
195 196 197
                        gNB->nr_gold_pdcch_dmrs[slot],
                        &gNB->common_vars.txdataF[0][txdataF_offset],  // hardcoded to beam 0
                        AMP, *fp, *cfg);
198

199 200 201 202 203 204 205 206 207 208
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
  }
      
  for (int i=0; i<num_pdsch_rnti; i++) {
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
    LOG_D(PHY, "PDSCH generation started (%d)\n", num_pdsch_rnti);
    nr_generate_pdsch(gNB->dlsch[i][0],
		      &gNB->pdcch_vars.dci_alloc[i],
		      gNB->nr_gold_pdsch_dmrs[slot],
		      gNB->common_vars.txdataF,
209 210 211 212
		      AMP, frame, slot, fp, cfg,
		      &gNB->dlsch_encoding_stats,
		      &gNB->dlsch_scrambling_stats,
		      &gNB->dlsch_modulation_stats);
213
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
214
  }
215

216
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0);
Guy De Souza's avatar
Guy De Souza committed
217
}
218 219


220
void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int UE_id, uint8_t harq_pid)
221 222
{
  NR_DL_FRAME_PARMS                    *frame_parms           = &gNB->frame_parms;
223
  nfapi_nr_ul_config_ulsch_pdu         *rel15_ul              = &gNB->ulsch[UE_id][0]->harq_processes[harq_pid]->ulsch_pdu;
224 225
  nfapi_nr_ul_config_ulsch_pdu_rel15_t *nfapi_ulsch_pdu_rel15 = &rel15_ul->ulsch_pdu_rel15;
  
226
  uint8_t ret;
227 228
  uint8_t l, number_dmrs_symbols = 0;
  uint8_t mapping_type;
229 230 231
  uint32_t G;
  int Nid_cell = 0; // [hna] shouldn't be a local variable (should be signaled)

232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
  mapping_type = gNB->pusch_config.pusch_TimeDomainResourceAllocation[0]->mappingType;
  gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->nb_re_dmrs = 0;

  for (l = 0; l < NR_SYMBOLS_PER_SLOT; l++)
      number_dmrs_symbols += is_dmrs_symbol(l,
                                            0,
                                            0,
                                            0,
                                            0,
                                            0,
                                            nfapi_ulsch_pdu_rel15->number_symbols,
                                            &gNB->dmrs_UplinkConfig,
                                            mapping_type,
                                            frame_parms->ofdm_symbol_size);

  gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->nb_re_dmrs = ((gNB->dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)?6:4)*number_dmrs_symbols;

249 250
  G = nr_get_G(nfapi_ulsch_pdu_rel15->number_rbs,
               nfapi_ulsch_pdu_rel15->number_symbols,
251
               gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->nb_re_dmrs,
yilmazt's avatar
yilmazt committed
252 253 254
               nfapi_ulsch_pdu_rel15->length_dmrs,
               nfapi_ulsch_pdu_rel15->Qm,
               nfapi_ulsch_pdu_rel15->n_layers);
255 256 257 258 259

  //----------------------------------------------------------
  //------------------- ULSCH unscrambling -------------------
  //----------------------------------------------------------

260
  nr_ulsch_unscrambling(gNB->pusch_vars[UE_id]->llr,
yilmazt's avatar
yilmazt committed
261 262 263 264
                        G,
                        0,
                        Nid_cell,
                        rel15_ul->rnti);
265 266 267 268 269

  //----------------------------------------------------------
  //--------------------- ULSCH decoding ---------------------
  //----------------------------------------------------------

270
  ret = nr_ulsch_decoding(gNB,
271
                    UE_id,
yilmazt's avatar
yilmazt committed
272 273
                    gNB->pusch_vars[UE_id]->llr,
                    frame_parms,
274
                    frame_rx,
yilmazt's avatar
yilmazt committed
275
                    nfapi_ulsch_pdu_rel15->number_symbols,
276
                    slot_rx,
yilmazt's avatar
yilmazt committed
277 278
                    harq_pid,
                    0);
279
        
280 281 282 283
  if (ret > gNB->ulsch[UE_id][0]->max_ldpc_iterations)
    LOG_I(PHY, "ULSCH in error\n");
  else
    LOG_I(PHY, "ULSCH received ok\n");
284 285 286 287

}


288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
void nr_fill_rx_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int UE_id, uint8_t harq_pid)
{
  // --------------------
  // [hna] TO BE CLEANED
  // --------------------

  // nfapi_rx_indication_pdu_t *pdu;

  int timing_advance_update;
  int sync_pos;

  // pthread_mutex_lock(&gNB->UL_INFO_mutex);

  // gNB->UL_INFO.rx_ind.sfn_sf                    = frame<<4| slot_rx;
  // gNB->UL_INFO.rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG;

  // pdu                                    = &gNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list[gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus];

  // pdu->rx_ue_information.handle          = gNB->ulsch[UE_id+1][0]->handle;
  // pdu->rx_ue_information.tl.tag          = NFAPI_RX_UE_INFORMATION_TAG;
  // pdu->rx_ue_information.rnti            = gNB->ulsch[UE_id+1][0]->rnti;
  // pdu->rx_indication_rel8.tl.tag         = NFAPI_RX_INDICATION_REL8_TAG;
  // pdu->rx_indication_rel8.length         = gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->TBS>>3;
  // pdu->rx_indication_rel8.offset         = 1;   // DJP - I dont understand - but broken unless 1 ????  0;  // filled in at the end of the UL_INFO formation
  // pdu->data                              = gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->b;
  // estimate timing advance for MAC
  sync_pos                               = nr_est_timing_advance_pusch(gNB, UE_id);
  timing_advance_update                  = sync_pos; // - gNB->frame_parms.nb_prefix_samples/4; //to check
  // printf("\x1B[33m" "timing_advance_update = %d\n" "\x1B[0m", timing_advance_update);

  switch (gNB->frame_parms.N_RB_DL) {
    // case 6:   /* nothing to do */          break;
    // case 15:  timing_advance_update /= 2;  break;
    // case 25:  timing_advance_update /= 4;  break;
    // case 50:  timing_advance_update /= 8;  break;
    // case 75:  timing_advance_update /= 12; break;
    case 106: timing_advance_update /= 16; break;
    case 217: timing_advance_update /= 32; break;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
326
    case 273: timing_advance_update /= 32; break;
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
    default: abort();
  }

  // put timing advance command in 0..63 range
  timing_advance_update += 31;

  if (timing_advance_update < 0)  timing_advance_update = 0;
  if (timing_advance_update > 63) timing_advance_update = 63;

  // pdu->rx_indication_rel8.timing_advance = timing_advance_update;

  // estimate UL_CQI for MAC (from antenna port 0 only)
  // int SNRtimes10 = dB_fixed_times10(gNB->pusch_vars[UE_id]->ulsch_power[0]) - 300;//(10*gNB->measurements.n0_power_dB[0]);

  // if      (SNRtimes10 < -640) pdu->rx_indication_rel8.ul_cqi=0;
  // else if (SNRtimes10 >  635) pdu->rx_indication_rel8.ul_cqi=255;
  // else                        pdu->rx_indication_rel8.ul_cqi=(640+SNRtimes10)/5;

  // LOG_D(PHY,"[PUSCH %d] Frame %d Subframe %d Filling RX_indication with SNR %d (%d), timing_advance %d (update %d)\n",
  // harq_pid,frame,slot_rx,SNRtimes10,pdu->rx_indication_rel8.ul_cqi,pdu->rx_indication_rel8.timing_advance,
  // timing_advance_update);

  // gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus++;
  // gNB->UL_INFO.rx_ind.sfn_sf = frame<<4 | slot_rx;

  // pthread_mutex_unlock(&gNB->UL_INFO_mutex);
}


356
void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
357 358

  uint8_t symbol;
359
  unsigned char aa;
360 361

  for(symbol = 0; symbol < NR_SYMBOLS_PER_SLOT; symbol++) {
362 363 364 365 366 367
    // nr_slot_fep_ul(gNB, symbol, proc->slot_rx, 0, 0);
    for (aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) {
      nr_slot_fep_ul(&gNB->frame_parms,
                     gNB->common_vars.rxdata[aa],
                     gNB->common_vars.rxdataF[aa],
                     symbol,
368
                     slot_rx,
369 370 371
                     0,
                     0);
    }
372
  }
373 374 375

}

376
void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
377

378 379
  nfapi_nr_ul_tti_request_t     *UL_tti_req  = &gNB->UL_tti_req;
  int num_pusch_pdu = UL_tti_req->n_pdus;
380

381
  LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d, num_pusch_pdu %d\n",frame_rx,slot_rx,num_pusch_pdu);
382
  
383
  for (int i = 0; i < num_pusch_pdu; i++) {
384

385 386 387
    switch (UL_tti_req->pdus_list[i].pdu_type) {
    case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE:
      {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
388
	LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE\n",frame_rx,slot_rx);
389

390 391 392 393 394
	nfapi_nr_pusch_pdu_t  *pusch_pdu = &UL_tti_req->pdus_list[0].pusch_pdu;
	nr_fill_ulsch(gNB,frame_rx,slot_rx,pusch_pdu);      
	
	uint8_t UE_id =  find_nr_ulsch(pusch_pdu->rnti,gNB,SEARCH_EXIST);
	uint8_t harq_pid = pusch_pdu->pusch_data.harq_process_id;
395 396
	uint8_t symbol_start = pusch_pdu->start_symbol_index;
	uint8_t symbol_end = symbol_start + pusch_pdu->nr_of_symbols;
397 398 399 400
	
	for(uint8_t symbol = symbol_start; symbol < symbol_end; symbol++) {
	  nr_rx_pusch(gNB, UE_id, frame_rx, slot_rx, symbol, harq_pid);
	}
401 402
	//LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[UE_id]->rxdataF_comp[0],6900,1,1);
	//LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[UE_id]->rxdataF_ext[0],6900,1,1);
403 404 405
	nr_ulsch_procedures(gNB, frame_rx, slot_rx, UE_id, harq_pid);
	nr_fill_rx_indication(gNB, frame_rx, slot_rx, UE_id, harq_pid);  // indicate SDU to MAC
      }
406 407 408
    }
  }
}