gNB_scheduler_RA.c 92.6 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 23 24 25 26
/*! \file     gNB_scheduler_RA.c
 * \brief     primitives used for random access
 * \author    Guido Casati
 * \date      2019
 * \email:    guido.casati@iis.fraunhofer.de
27 28 29
 * \version
 */

30
#include "common/platform_types.h"
31
#include "uper_decoder.h"
32

cig's avatar
cig committed
33
/* MAC */
34 35 36
#include "nr_mac_gNB.h"
#include "NR_MAC_gNB/mac_proto.h"
#include "NR_MAC_COMMON/nr_mac_extern.h"
37

cig's avatar
cig committed
38 39 40
/* Utils */
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
cig's avatar
cig committed
41
#include "common/utils/nr/nr_common.h"
42
#include "UTIL/OPT/opt.h"
cig's avatar
cig committed
43
#include "SIMULATION/TOOLS/sim.h" // for taus
44

45 46
/* rlc */
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
47
#include "openair2/LAYER2/RLC/rlc.h"
48

Raymond Knopp's avatar
Raymond Knopp committed
49
#include <executables/softmodem-common.h>
cig's avatar
cig committed
50
extern RAN_CONTEXT_t RC;
cig's avatar
cig committed
51
extern const uint8_t nr_slots_per_frame[5];
52
extern uint16_t sl_ahead;
53

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
// forward declaration of functions used in this file
static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu,
                                NR_ServingCellConfigCommon_t *scc,
                                int round,
                                int startSymbolAndLength,
                                rnti_t rnti,
                                int scs,
                                int bwp_size,
                                int bwp_start,
                                int mappingtype,
                                int fh,
                                int msg3_first_rb,
                                int msg3_nb_rb);
static void nr_fill_rar(uint8_t Mod_idP, NR_RA_t *ra, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu);

laurent's avatar
laurent committed
69
static const uint8_t DELTA[4] = {2, 3, 4, 6};
70

laurent's avatar
laurent committed
71
static const float ssb_per_rach_occasion[8] = {0.125, 0.25, 0.5, 1, 2, 4, 8};
72

73 74 75 76 77 78 79
static int16_t ssb_index_from_prach(module_id_t module_idP,
                                    frame_t frameP,
                                    sub_frame_t slotP,
                                    uint16_t preamble_index,
                                    uint8_t freq_index,
                                    uint8_t symbol)
{
Florian Kaltenberger's avatar
Florian Kaltenberger committed
80
  gNB_MAC_INST *gNB = RC.nrmac[module_idP];
81
  NR_COMMON_channels_t *cc = &gNB->common_channels[0];
82 83 84 85
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
  nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];

  uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
86
  uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
kn.raju's avatar
kn.raju committed
87
  
88
  uint8_t total_RApreambles = MAX_NUM_NR_PRACH_PREAMBLES;
89
  if( scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL)
kn.raju's avatar
kn.raju committed
90 91
    total_RApreambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles;	
  
92
  float  num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];	
93
  uint16_t start_symbol_index = 0;
94
  uint8_t mu,N_dur=0,N_t_slot=0,start_symbol = 0, temp_start_symbol = 0, N_RA_slot=0;
kn.raju's avatar
kn.raju committed
95
  uint16_t format,RA_sfn_index = -1;
96
  uint8_t config_period = 1;
kn.raju's avatar
kn.raju committed
97
  uint16_t prach_occasion_id = -1;
98
  uint8_t num_active_ssb = cc->num_active_ssb;
99 100 101 102 103 104 105

  if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing)
    mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
  else
    mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;

  get_nr_prach_info_from_index(config_index,
106 107 108 109 110 111 112 113 114 115 116 117
			       (int)frameP,
			       (int)slotP,
			       scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
			       mu,
			       cc->frame_type,
			       &format,
			       &start_symbol,
			       &N_t_slot,
			       &N_dur,
			       &RA_sfn_index,
			       &N_RA_slot,
			       &config_period);
kn.raju's avatar
kn.raju committed
118
  uint8_t index = 0,slot_index = 0;
119
  for (slot_index = 0;slot_index < N_RA_slot; slot_index++) {
120 121 122 123
    if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
       if((mu == 1) || (mu == 3))
         slot_index = 1;  //For scs = 30khz and 120khz
    }
kn.raju's avatar
kn.raju committed
124 125
    for (int i=0; i< N_t_slot; i++) {
      temp_start_symbol = (start_symbol + i * N_dur + 14 * slot_index) % 14;
126 127 128 129 130 131
      if(symbol == temp_start_symbol) {
        start_symbol_index = i;
        break;
      }
    }
  }
kn.raju's avatar
kn.raju committed
132 133 134 135
  if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
    if((mu == 1) || (mu == 3))
      slot_index = 0;  //For scs = 30khz and 120khz
  }
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

  //  prach_occasion_id = subframe_index * N_t_slot * N_RA_slot * fdm + N_RA_slot_index * N_t_slot * fdm + freq_index + fdm * start_symbol_index; 
  prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period)*cc->total_prach_occasions_per_config_period) +
                      (RA_sfn_index + slot_index) * N_t_slot * fdm + start_symbol_index * fdm + freq_index; 

  //one RO is shared by one or more SSB
  if(num_ssb_per_RO <= 1 )
    index = (int) (prach_occasion_id / (int)(1/num_ssb_per_RO)) % num_active_ssb;
  //one SSB have more than one continuous RO
  else if ( num_ssb_per_RO > 1) {
    index = (prach_occasion_id * (int)num_ssb_per_RO)% num_active_ssb ;
    for(int j = 0;j < num_ssb_per_RO;j++) {
      if(preamble_index <  (((j+1) * total_RApreambles) / num_ssb_per_RO))
        index = index + j;
    }
  }

153
  LOG_D(NR_MAC, "Frame %d, Slot %d: Prach Occasion id = %d ssb per RO = %f number of active SSB %u index = %d fdm %u symbol index %u freq_index %u total_RApreambles %u\n",
154 155
        frameP, slotP, prach_occasion_id, num_ssb_per_RO, num_active_ssb, index, fdm, start_symbol_index, freq_index, total_RApreambles);

156 157
  return index;
}
158

159
//Compute Total active SSBs and RO available
160 161
void find_SSB_and_RO_available(gNB_MAC_INST *nrmac)
{
162
  /* already mutex protected through nr_mac_config_scc() */
163
  //NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
164

165
  NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
166
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
167
  nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0];
168 169

  uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
170
  uint8_t mu,N_dur=0,N_t_slot=0,start_symbol=0,N_RA_slot = 0;
kn.raju's avatar
kn.raju committed
171
  uint16_t format,N_RA_sfn = 0,unused_RA_occasion,repetition = 0;
172
  uint8_t num_active_ssb = 0;
173
  uint8_t max_association_period = 1;
174

kn.raju's avatar
kn.raju committed
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
  struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *ssb_perRACH_OccasionAndCB_PreamblesPerSSB = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB;

  switch (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present){
    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
      cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1);
      break;
    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
      cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1);
      break;
    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
      cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1);
      break;
    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
      cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1);
      break;
    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
      cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1);
      break;
    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four:
      cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four;
      break;
    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight:
      cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight;
      break;
    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen:
      cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen;
      break;
    default:
      AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present);
      break;
    }

207 208 209 210 211 212 213
  if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing)
    mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
  else
    mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;

  // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4
  get_nr_prach_occasion_info_from_index(config_index,
214 215 216 217 218 219 220 221 222 223
                                        scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
                                        mu,
                                        cc->frame_type,
                                        &format,
                                        &start_symbol,
                                        &N_t_slot,
                                        &N_dur,
                                        &N_RA_slot,
                                        &N_RA_sfn,
                                        &max_association_period);
224 225

  float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];	
226
  uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
227
  uint64_t L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value)<<32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value ;
228
  uint32_t total_RA_occasions = N_RA_sfn * N_t_slot * N_RA_slot * fdm;
229

230
  for(int i = 0;i < 64;i++) {
231
    if ((L_ssb >> (63-i)) & 0x01) { // only if the bit of L_ssb at current ssb index is 1
232
      cc->ssb_index[num_active_ssb] = i; 
233
      num_active_ssb++;
234
    }
235
  }
236

kn.raju's avatar
kn.raju committed
237
  cc->total_prach_occasions_per_config_period = total_RA_occasions;
238
  for(int i=1; (1 << (i-1)) <= max_association_period; i++) {
kn.raju's avatar
kn.raju committed
239 240
    cc->max_association_period = (1 <<(i-1));
    total_RA_occasions = total_RA_occasions * cc->max_association_period;
241
    if(total_RA_occasions >= (int) (num_active_ssb/num_ssb_per_RO)) {
242 243 244 245
      repetition = (uint16_t)((total_RA_occasions * num_ssb_per_RO )/num_active_ssb);
      break;
    }
  }
246

247 248 249
  unused_RA_occasion = total_RA_occasions - (int)((num_active_ssb * repetition)/num_ssb_per_RO);
  cc->total_prach_occasions = total_RA_occasions - unused_RA_occasion;
  cc->num_active_ssb = num_active_ssb;
kn.raju's avatar
kn.raju committed
250

251
  LOG_D(NR_MAC,
kn.raju's avatar
kn.raju committed
252 253 254 255 256 257 258
        "Total available RO %d, num of active SSB %d: unused RO = %d association_period %u N_RA_sfn %u total_prach_occasions_per_config_period %u\n",
        cc->total_prach_occasions,
        cc->num_active_ssb,
        unused_RA_occasion,
        cc->max_association_period,
        N_RA_sfn,
        cc->total_prach_occasions_per_config_period);
259 260
}		
		
261 262
void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
{
263
  gNB_MAC_INST *gNB = RC.nrmac[module_idP];
264 265 266
  /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
  NR_SCHED_ENSURE_LOCKED(&gNB->sched_lock);

267 268
  NR_COMMON_channels_t *cc = gNB->common_channels;
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
269 270 271 272 273 274 275
  int mu;
  if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing)
    mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
  else
    mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
  int index = ul_buffer_index(frameP, slotP, mu, gNB->UL_tti_req_ahead_size);
  nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][index];
276
  nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
277

278
  if (is_nr_UL_slot(scc->tdd_UL_DL_ConfigurationCommon, slotP, cc->frame_type)) {
279

280
    uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
281
    uint8_t N_dur, N_t_slot, start_symbol = 0, N_RA_slot;
282 283 284 285 286 287
    uint16_t RA_sfn_index = -1;
    uint8_t config_period = 1;
    uint16_t format;
    int slot_index = 0;
    uint16_t prach_occasion_id = -1;

francescomani's avatar
francescomani committed
288 289
    int bwp_start = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);

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
    uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
    // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4
    if ( get_nr_prach_info_from_index(config_index,
                                      (int)frameP,
                                      (int)slotP,
                                      scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
                                      mu,
                                      cc->frame_type,
                                      &format,
                                      &start_symbol,
                                      &N_t_slot,
                                      &N_dur,
                                      &RA_sfn_index,
                                      &N_RA_slot,
                                      &config_period) ) {

      uint16_t format0 = format&0xff;      // first column of format from table
      uint16_t format1 = (format>>8)&0xff; // second column of format from table

      if (N_RA_slot > 1) { //more than 1 PRACH slot in a subframe
        if (slotP%2 == 1)
          slot_index = 1;
        else
          slot_index = 0;
      }else if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
        slot_index = 0;
      }
317

318 319 320 321 322 323 324 325 326
      UL_tti_req->SFN = frameP;
      UL_tti_req->Slot = slotP;
      for (int fdm_index=0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion
        for (int td_index=0; td_index<N_t_slot; td_index++) {

          prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) +
                              (RA_sfn_index + slot_index) * N_t_slot * fdm + td_index * fdm + fdm_index;

          if((prach_occasion_id < cc->total_prach_occasions) && (td_index == 0)){
327 328
            AssertFatal(UL_tti_req->n_pdus < sizeof(UL_tti_req->pdus_list) / sizeof(UL_tti_req->pdus_list[0]),
                        "Invalid UL_tti_req->n_pdus %d\n", UL_tti_req->n_pdus);
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344

            UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE;
            UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_prach_pdu_t);
            nfapi_nr_prach_pdu_t  *prach_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].prach_pdu;
            memset(prach_pdu,0,sizeof(nfapi_nr_prach_pdu_t));
            UL_tti_req->n_pdus+=1;

            // filling the prach fapi structure
            prach_pdu->phys_cell_id = *scc->physCellId;
            prach_pdu->num_prach_ocas = N_t_slot;
            prach_pdu->prach_start_symbol = start_symbol;
            prach_pdu->num_ra = fdm_index;
            prach_pdu->num_cs = get_NCS(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig,
                                        format0,
                                        scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig);

345
            LOG_D(NR_MAC, "Frame %d, Slot %d: Prach Occasion id = %u  fdm index = %u start symbol = %u slot index = %u subframe index = %u \n",
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
                  frameP, slotP,
                  prach_occasion_id, prach_pdu->num_ra,
                  prach_pdu->prach_start_symbol,
                  slot_index, RA_sfn_index);
            // SCF PRACH PDU format field does not consider A1/B1 etc. possibilities
            // We added 9 = A1/B1 10 = A2/B2 11 A3/B3
            if (format1!=0xff) {
              switch(format0) {
                case 0xa1:
                  prach_pdu->prach_format = 11;
                  break;
                case 0xa2:
                  prach_pdu->prach_format = 12;
                  break;
                case 0xa3:
                  prach_pdu->prach_format = 13;
                  break;
              default:
                AssertFatal(1==0,"Only formats A1/B1 A2/B2 A3/B3 are valid for dual format");
              }
            }
            else{
              switch(format0) {
                case 0:
                  prach_pdu->prach_format = 0;
                  break;
                case 1:
                  prach_pdu->prach_format = 1;
                  break;
                case 2:
                  prach_pdu->prach_format = 2;
                  break;
                case 3:
                  prach_pdu->prach_format = 3;
                  break;
                case 0xa1:
                  prach_pdu->prach_format = 4;
                  break;
                case 0xa2:
                  prach_pdu->prach_format = 5;
                  break;
                case 0xa3:
                  prach_pdu->prach_format = 6;
                  break;
                case 0xb1:
                  prach_pdu->prach_format = 7;
                  break;
                case 0xb4:
                  prach_pdu->prach_format = 8;
                  break;
                case 0xc0:
                  prach_pdu->prach_format = 9;
                  break;
                case 0xc2:
                  prach_pdu->prach_format = 10;
                  break;
              default:
                AssertFatal(1==0,"Invalid PRACH format");
              }
            }
          }
407
        }
408
      }
409 410 411 412 413 414 415

      // block resources in vrb_map_UL
      const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric =
          &scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric;
      const uint8_t mu_pusch =
          scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
      const int16_t N_RA_RB = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch);
416 417
      index = ul_buffer_index(frameP, slotP, mu, gNB->vrb_map_UL_size);
      uint16_t *vrb_map_UL = &cc->vrb_map_UL[index * MAX_BWP_SIZE];
418
      for (int i = 0; i < N_RA_RB * fdm; ++i)
francescomani's avatar
francescomani committed
419
        vrb_map_UL[bwp_start + rach_ConfigGeneric->msg1_FrequencyStart + i] |= SL_to_bitmap(start_symbol, N_t_slot*N_dur);
420 421 422 423
    }
  }
}

424 425 426 427 428 429 430 431 432 433 434 435 436 437
static void nr_schedule_msg2(uint16_t rach_frame,
                             uint16_t rach_slot,
                             uint16_t *msg2_frame,
                             uint16_t *msg2_slot,
                             int mu,
                             NR_ServingCellConfigCommon_t *scc,
                             frame_type_t frame_type,
                             uint16_t monitoring_slot_period,
                             uint16_t monitoring_offset,
                             uint8_t beam_index,
                             uint8_t num_active_ssb,
                             int16_t *tdd_beam_association,
                             int sl_ahead)
{
438 439 440 441
  // preferentially we schedule the msg2 in the mixed slot or in the last dl slot
  // if they are allowed by search space configuration
  uint8_t response_window = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow;
  uint8_t slot_window;
442
  const int n_slots_frame = nr_slots_per_frame[mu];
443
  const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
444
  // number of mixed slot or of last dl slot if there is no mixed slot
445
  uint8_t last_dl_slot_period = n_slots_frame-1;
446
  // lenght of tdd period in slots
447
  uint8_t tdd_period_slot = n_slots_frame;
448

449 450 451
  if (tdd) {
    last_dl_slot_period = tdd->nrofDownlinkSymbols == 0? (tdd->nrofDownlinkSlots-1) : tdd->nrofDownlinkSlots;
    tdd_period_slot = n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
452
  }
453 454
  else{
    if(frame_type == TDD)
455
      AssertFatal(frame_type == FDD, "Dynamic TDD not handled yet\n");
456
  }
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486


  switch(response_window){
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1:
      slot_window = 1;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2:
      slot_window = 2;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4:
      slot_window = 4;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8:
      slot_window = 8;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10:
      slot_window = 10;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20:
      slot_window = 20;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40:
      slot_window = 40;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80:
      slot_window = 80;
      break;
    default:
      AssertFatal(1==0,"Invalid response window value %d\n",response_window);
  }
cig's avatar
cig committed
487
  AssertFatal(slot_window<=nr_slots_per_frame[mu],"Msg2 response window needs to be lower or equal to 10ms");
488 489

  // slot and frame limit to transmit msg2 according to response window
cig's avatar
cig committed
490
  uint8_t slot_limit = (rach_slot + slot_window)%nr_slots_per_frame[mu];
Thomas Schlichter's avatar
Thomas Schlichter committed
491
  uint16_t frame_limit = rach_frame + (rach_slot + slot_window)/nr_slots_per_frame[mu];
492

493
  // computing start of next period
laurent's avatar
laurent committed
494 495
  uint8_t start_next_period = rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot;
  int eff_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot
Thomas Schlichter's avatar
Thomas Schlichter committed
496

497
  // we can't schedule msg2 before sl_ahead since prach
francescomani's avatar
francescomani committed
498
  while ((eff_slot-rach_slot)<=sl_ahead) {
laurent's avatar
laurent committed
499
    eff_slot += tdd_period_slot;
500
  }
Thomas Schlichter's avatar
Thomas Schlichter committed
501 502

  int FR = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] >= 257 ? nr_FR2 : nr_FR1;
503
  if (FR==nr_FR2) {
laurent's avatar
laurent committed
504
    int num_tdd_period = (eff_slot%nr_slots_per_frame[mu])/tdd_period_slot;
505
    while((tdd_beam_association[num_tdd_period]!=-1)&&(tdd_beam_association[num_tdd_period]!=beam_index)) {
laurent's avatar
laurent committed
506 507
      eff_slot += tdd_period_slot;
      num_tdd_period = (eff_slot % nr_slots_per_frame[mu])/tdd_period_slot;
508 509 510 511 512
    }
    if(tdd_beam_association[num_tdd_period] == -1)
      tdd_beam_association[num_tdd_period] = beam_index;
  }

Thomas Schlichter's avatar
Thomas Schlichter committed
513 514 515
  *msg2_frame = rach_frame + eff_slot / nr_slots_per_frame[mu];
  *msg2_slot = eff_slot % nr_slots_per_frame[mu];

516 517
  // go to previous slot if the current scheduled slot is beyond the response window
  // and if the slot is not among the PDCCH monitored ones (38.213 10.1)
francescomani's avatar
francescomani committed
518 519 520
  while (*msg2_frame > frame_limit
         || (*msg2_frame == frame_limit && *msg2_slot > slot_limit)
         || ((*msg2_frame * nr_slots_per_frame[mu] + *msg2_slot - monitoring_offset) % monitoring_slot_period != 0)) {
francescomani's avatar
francescomani committed
521

522 523
    if((frame_type == FDD) || ((*msg2_slot%tdd_period_slot) > 0)) {
      if (*msg2_slot==0) {
Thomas Schlichter's avatar
Thomas Schlichter committed
524
        (*msg2_frame)--;
525 526 527 528
        *msg2_slot = nr_slots_per_frame[mu] - 1;
      }
      else
        (*msg2_slot)--;
francescomani's avatar
francescomani committed
529
    }
530 531 532
    else
      AssertFatal(1==0,"No available DL slot to schedule msg2 has been found");
  }
Thomas Schlichter's avatar
Thomas Schlichter committed
533 534 535

  // calculate frame number considering wrap-around
  *msg2_frame = *msg2_frame % 1024;
cig's avatar
cig committed
536
}
537

538

539 540 541 542 543
void nr_initiate_ra_proc(module_id_t module_idP,
                         int CC_id,
                         frame_t frameP,
                         sub_frame_t slotP,
                         uint16_t preamble_index,
544 545
                         uint8_t freq_index,
                         uint8_t symbol,
546 547 548 549
                         int16_t timing_offset)
{
  gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
  NR_SCHED_LOCK(&nr_mac->sched_lock);
550

551 552
  uint8_t ul_carrier_id = 0; // 0 for NUL 1 for SUL
  uint16_t msg2_frame, msg2_slot,monitoring_slot_period,monitoring_offset;
cig's avatar
cig committed
553
  NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
554
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
francescomani's avatar
francescomani committed
555
  frame_type_t frame_type = cc->frame_type;
556

557
  uint8_t total_RApreambles = MAX_NUM_NR_PRACH_PREAMBLES;
558
  uint8_t  num_ssb_per_RO = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present;
559
  int pr_found;
560

kn.raju's avatar
kn.raju committed
561
  if( scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL)
562
    total_RApreambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles;
563

kn.raju's avatar
kn.raju committed
564 565 566
  if(num_ssb_per_RO > 3) { /*num of ssb per RO >= 1*/
    num_ssb_per_RO -= 3;
    total_RApreambles = total_RApreambles/num_ssb_per_RO ;
567
  }
568

569
  for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
francescomani's avatar
francescomani committed
570

571
    NR_RA_t *ra = &cc->ra[i];
francescomani's avatar
francescomani committed
572
    if (ra->state != RA_IDLE)
573
      continue;
574

francescomani's avatar
francescomani committed
575
    pr_found = 0;
rmagueta's avatar
rmagueta committed
576

francescomani's avatar
francescomani committed
577 578 579 580 581 582 583
    for(int j = 0; j < ra->preambles.num_preambles; j++) {
      //check if the preamble received correspond to one of the listed or configured preambles
      if (preamble_index == ra->preambles.preamble_list[j]) {
        if (ra->rnti == 0 && get_softmodem_params()->nsa)
          continue;
        pr_found=1;
        break;
584
      }
francescomani's avatar
francescomani committed
585 586 587 588
    }
    if (pr_found == 0) {
       continue;
    }
589

590
    rnti_t ra_rnti = nr_get_ra_rnti(symbol, slotP, freq_index, ul_carrier_id);
francescomani's avatar
francescomani committed
591

592
    // Configure RA BWP
593
    configure_UE_BWP(nr_mac, scc, NULL, ra, NULL, -1, -1);
594

francescomani's avatar
francescomani committed
595
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1);
596

francescomani's avatar
francescomani committed
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
    LOG_D(NR_MAC,
          "[gNB %d][RAPROC] CC_id %d Frame %d, Slot %d  Initiating RA procedure for preamble index %d\n",
          module_idP,
          CC_id,
          frameP,
          slotP,
          preamble_index);

    uint8_t beam_index = ssb_index_from_prach(module_idP, frameP, slotP, preamble_index, freq_index, symbol);

    // the UE sent a RACH either for starting RA procedure or RA procedure failed and UE retries
    if (ra->cfra) {
      // if the preamble received correspond to one of the listed
      if (!(preamble_index == ra->preambles.preamble_list[beam_index])) {
        LOG_E(
            NR_MAC,
            "[gNB %d][RAPROC] FAILURE: preamble %d does not correspond to any of the ones in rach_ConfigDedicated\n",
614 615
            module_idP,
            preamble_index);
francescomani's avatar
francescomani committed
616
        continue; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc
Francesco Mani's avatar
Francesco Mani committed
617
      }
francescomani's avatar
francescomani committed
618 619 620 621 622
    }
    LOG_D(NR_MAC, "Frame %d, Slot %d: Activating RA process \n", frameP, slotP);
    ra->state = Msg2;
    ra->timing_offset = timing_offset;
    ra->preamble_slot = slotP;
623

francescomani's avatar
francescomani committed
624 625 626 627 628 629 630
    // retrieving ra pdcch monitoring period and offset
    find_monitoring_periodicity_offset_common(ra->ra_ss, &monitoring_slot_period, &monitoring_offset);

    nr_schedule_msg2(frameP,
                     slotP,
                     &msg2_frame,
                     &msg2_slot,
631
                     ra->DL_BWP.scs,
francescomani's avatar
francescomani committed
632 633 634 635 636 637 638
                     scc,
                     frame_type,
                     monitoring_slot_period,
                     monitoring_offset,
                     beam_index,
                     cc->num_active_ssb,
                     nr_mac->tdd_beam_association,
639
                     nr_mac->if_inst->sl_ahead);
francescomani's avatar
francescomani committed
640 641 642 643 644 645 646 647 648

    ra->Msg2_frame = msg2_frame;
    ra->Msg2_slot = msg2_slot;

    LOG_D(NR_MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP);

    int loop = 0;
    if (ra->rnti == 0) { // This condition allows for the usage of a preconfigured rnti for the CFRA
      do {
649 650
        // 3GPP TS 38.321 version 15.13.0 Section 7.1 Table 7.1-1: RNTI values
        ra->rnti = (taus() % 0xffef) + 1;
francescomani's avatar
francescomani committed
651 652 653
        loop++;
      } while (loop != 100
               && !((find_nr_UE(&nr_mac->UE_info, ra->rnti) == NULL) && (find_nr_RA_id(module_idP, CC_id, ra->rnti) == -1)
654
                    && ra->rnti >= 0x1 && ra->rnti <= 0xffef));
francescomani's avatar
francescomani committed
655 656 657
      if (loop == 100) {
        LOG_E(NR_MAC, "%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__);
        abort();
658
      }
cig's avatar
cig committed
659
    }
660

francescomani's avatar
francescomani committed
661 662
    ra->RA_rnti = ra_rnti;
    ra->preamble_index = preamble_index;
francescomani's avatar
francescomani committed
663
    ra->beam_id = cc->ssb_index[beam_index];
francescomani's avatar
francescomani committed
664 665 666 667 668 669 670 671 672 673

    LOG_I(NR_MAC,
          "[gNB %d][RAPROC] CC_id %d Frame %d Activating Msg2 generation in frame %d, slot %d using RA rnti %x SSB, new rnti %04x "
          "index %u RA index %d\n",
          module_idP,
          CC_id,
          frameP,
          ra->Msg2_frame,
          ra->Msg2_slot,
          ra->RA_rnti,
francescomani's avatar
francescomani committed
674
          ra->rnti,
francescomani's avatar
francescomani committed
675 676
          cc->ssb_index[beam_index],
          i);
677

678
    NR_SCHED_UNLOCK(&nr_mac->sched_lock);
francescomani's avatar
francescomani committed
679
    return;
680
  }
681 682

  NR_SCHED_UNLOCK(&nr_mac->sched_lock);
683
  LOG_E(NR_MAC, "[gNB %d][RAPROC] FAILURE: CC_id %d %4d.%2d initiating RA procedure for preamble index %d: no free RA process\n", module_idP, CC_id, frameP, slotP, preamble_index);
684

cig's avatar
cig committed
685
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0);
686 687
}

688 689 690 691 692 693 694 695 696 697 698 699 700 701 702
static void start_ra_contention_resolution_timer(NR_RA_t *ra, const long ra_ContentionResolutionTimer, const int K2, const int scs)
{
  // 3GPP TS 38.331 Section 6.3.2 Radio resource control information elements
  // ra-ContentionResolutionTimer ENUMERATED {sf8, sf16, sf24, sf32, sf40, sf48, sf56, sf64}
  // The initial value for the contention resolution timer.
  // Value sf8 corresponds to 8 subframes, value sf16 corresponds to 16 subframes, and so on.
  // We add K2 because we start the timer in the DL slot that schedules Msg3/Msg3 retransmission
  ra->contention_resolution_timer = ((((int)ra_ContentionResolutionTimer + 1) * 8) << scs) + K2;
  LOG_D(NR_MAC,
        "Starting RA Contention Resolution timer with %d ms + %d K2 (%d slots) duration\n",
        ((int)ra_ContentionResolutionTimer + 1) * 8,
        K2,
        ra->contention_resolution_timer);
}

703 704 705 706 707 708
static void nr_generate_Msg3_retransmission(module_id_t module_idP,
                                            int CC_id,
                                            frame_t frame,
                                            sub_frame_t slot,
                                            NR_RA_t *ra,
                                            nfapi_nr_ul_dci_request_t *ul_dci_req)
709
{
710 711 712
  gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
  NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
francescomani's avatar
francescomani committed
713
  NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP;
714
  NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info;
715

716
  NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = ul_bwp->tdaList_Common;
francescomani's avatar
francescomani committed
717
  int mu = ul_bwp->scs;
718
  uint8_t K2 = *pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2;
719
  const int sched_frame = (frame + (slot + K2 >= nr_slots_per_frame[mu])) % 1024;
720 721
  const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];

722
  if (is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) {
723 724 725
    // beam association for FR2
    int16_t *tdd_beam_association = nr_mac->tdd_beam_association;
    if (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] >= 257) {
726
      // FR2
727
      const int n_slots_frame = nr_slots_per_frame[mu];
728
      const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
729 730
      AssertFatal(tdd,"Dynamic TDD not handled yet\n");
      uint8_t tdd_period_slot = n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
731
      int num_tdd_period = sched_slot/tdd_period_slot;
732

733 734 735 736 737 738 739
      if((tdd_beam_association[num_tdd_period]!=-1)&&(tdd_beam_association[num_tdd_period]!=ra->beam_id))
        return; // can't schedule retransmission in this slot
      else
        tdd_beam_association[num_tdd_period] = ra->beam_id;
    }

    int fh = 0;
740
    int startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength;
741 742
    int StartSymbolIndex, NrOfSymbols;
    SLIV2SL(startSymbolAndLength, &StartSymbolIndex, &NrOfSymbols);
743
    int mappingtype = pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->mappingType;
744

745 746
    int buffer_index = ul_buffer_index(sched_frame, sched_slot, mu, nr_mac->vrb_map_UL_size);
    uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[buffer_index * MAX_BWP_SIZE];
747

748 749
    const int BWPSize = sc_info->initial_ul_BWPSize;
    const int BWPStart = sc_info->initial_ul_BWPStart;
750

751
    int rbStart = 0;
752
    for (int i = 0; (i < ra->msg3_nb_rb) && (rbStart <= (BWPSize - ra->msg3_nb_rb)); i++) {
753
      if (vrb_map_UL[rbStart + BWPStart + i]&SL_to_bitmap(StartSymbolIndex, NrOfSymbols)) {
754 755
        rbStart += i;
        i = 0;
756 757
      }
    }
758
    if (rbStart > (BWPSize - ra->msg3_nb_rb)) {
759 760 761 762
      // cannot find free vrb_map for msg3 retransmission in this slot
      return;
    }

763 764 765 766 767 768 769 770
    LOG_I(NR_MAC,
          "%4d%2d: RA RNTI %04x CC_id %d Scheduling retransmission of Msg3 in (%d,%d)\n",
          frame,
          slot,
          ra->rnti,
          CC_id,
          sched_frame,
          sched_slot);
771

772 773
    buffer_index = ul_buffer_index(sched_frame, sched_slot, mu, nr_mac->UL_tti_req_ahead_size);
    nfapi_nr_ul_tti_request_t *future_ul_tti_req = &nr_mac->UL_tti_req_ahead[CC_id][buffer_index];
774 775 776 777 778 779 780
    AssertFatal(future_ul_tti_req->SFN == sched_frame
                && future_ul_tti_req->Slot == sched_slot,
                "future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n",
                future_ul_tti_req->SFN,
                future_ul_tti_req->Slot,
                sched_frame,
                sched_slot);
781 782 783
    AssertFatal(future_ul_tti_req->n_pdus <
                sizeof(future_ul_tti_req->pdus_list) / sizeof(future_ul_tti_req->pdus_list[0]),
                "Invalid future_ul_tti_req->n_pdus %d\n", future_ul_tti_req->n_pdus);
784 785 786 787 788 789
    future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE;
    future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t);
    nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu;
    memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t));

    fill_msg3_pusch_pdu(pusch_pdu, scc,
790
                        ra->msg3_round,
791
                        startSymbolAndLength,
792
                        ra->rnti, mu,
793
                        BWPSize, BWPStart,
794 795 796 797 798 799
                        mappingtype, fh,
                        rbStart, ra->msg3_nb_rb);
    future_ul_tti_req->n_pdus += 1;

    // generation of DCI 0_0 to schedule msg3 retransmission
    NR_SearchSpace_t *ss = ra->ra_ss;
800
    NR_ControlResourceSet_t *coreset = ra->coreset;
801 802 803
    AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg3 retransmission\n");

    const int coresetid = coreset->controlResourceSetId;
804
    nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][coresetid];
805 806 807 808 809 810 811
    if (!pdcch_pdu_rel15) {
      nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus];
      memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t));
      ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
      ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
      pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15;
      ul_dci_req->numPdus += 1;
812
      nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch);
813
      nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15;
814 815 816
    }

    uint8_t aggregation_level;
817 818 819 820 821 822 823
    int CCEIndex = get_cce_index(nr_mac,
                                 CC_id, slot, 0,
                                 &aggregation_level,
                                 ss,
                                 coreset,
                                 &ra->sched_pdcch,
                                 true);
824
    if (CCEIndex < 0) {
825
      LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI 0x%04x!\n", __func__, ra->rnti);
826 827 828 829 830 831 832 833 834 835 836 837 838 839
      return;
    }

    // Fill PDCCH DL DCI PDU
    nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci];
    pdcch_pdu_rel15->numDlDci++;
    dci_pdu->RNTI = ra->rnti;
    dci_pdu->ScramblingId = *scc->physCellId;
    dci_pdu->ScramblingRNTI = 0;
    dci_pdu->AggregationLevel = aggregation_level;
    dci_pdu->CceIndex = CCEIndex;
    dci_pdu->beta_PDCCH_1_0 = 0;
    dci_pdu->powerControlOffsetSS = 1;

Laurent THOMAS's avatar
Laurent THOMAS committed
840
    dci_pdu_rel15_t uldci_payload={0};
841

Laurent THOMAS's avatar
Laurent THOMAS committed
842
    config_uldci(sc_info,
843 844
                 pusch_pdu,
                 &uldci_payload,
845
                 NULL,
846 847
                 ra->Msg3_tda_id,
                 ra->msg3_TPC,
848
                 1, // Not toggling NDI in msg3 retransmissions
849
                 ul_bwp);
850

851
    fill_dci_pdu_rel15(sc_info,
852
                       &ra->DL_BWP,
853
                       ul_bwp,
854 855 856
                       dci_pdu,
                       &uldci_payload,
                       NR_UL_DCI_FORMAT_0_0,
857
                       TYPE_TC_RNTI_,
francescomani's avatar
francescomani committed
858
                       ul_bwp->bwp_id,
859
                       ss,
860
                       coreset,
861
                       0, // parameter not needed for DCI 0_0
862
                       nr_mac->cset0_bwp_size);
863 864

    // Mark the corresponding RBs as used
865 866 867

    fill_pdcch_vrb_map(nr_mac,
                       CC_id,
868
                       &ra->sched_pdcch,
869 870 871
                       CCEIndex,
                       aggregation_level);

872
    for (int rb = 0; rb < ra->msg3_nb_rb; rb++) {
873
      vrb_map_UL[rbStart + BWPStart + rb] |= SL_to_bitmap(StartSymbolIndex, NrOfSymbols);
874 875
    }

876 877 878 879 880 881 882 883
    // Restart RA contention resolution timer in Msg3 retransmission slot (current slot + K2)
    // 3GPP TS 38.321 Section 5.1.5 Contention Resolution
    start_ra_contention_resolution_timer(
        ra,
        scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer,
        K2,
        ra->UL_BWP.scs);

884 885
    // reset state to wait msg3
    ra->state = WAIT_Msg3;
francescomani's avatar
francescomani committed
886 887
    ra->Msg3_frame = sched_frame;
    ra->Msg3_slot = sched_slot;
888

cig's avatar
cig committed
889
  }
890
}
891

892 893 894 895 896 897 898
static void nr_get_Msg3alloc(module_id_t module_id,
                             int CC_id,
                             NR_ServingCellConfigCommon_t *scc,
                             sub_frame_t current_slot,
                             frame_t current_frame,
                             NR_RA_t *ra,
                             int16_t *tdd_beam_association)
899
{
900 901
  // msg3 is scheduled in mixed slot in the following TDD period

902
  uint16_t msg3_nb_rb = 8; // sdu has 6 or 8 bytes
903 904
  gNB_MAC_INST *mac = RC.nrmac[module_id];
  frame_type_t frame_type = mac->common_channels->frame_type;
905

francescomani's avatar
francescomani committed
906
  NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP;
907
  NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info;
908

francescomani's avatar
francescomani committed
909
  int mu = ul_bwp->scs;
910 911 912
  int StartSymbolIndex = 0;
  int NrOfSymbols = 0;
  int startSymbolAndLength = 0;
francescomani's avatar
francescomani committed
913
  int abs_slot = 0;
Raymond Knopp's avatar
Raymond Knopp committed
914
  int Msg3maxsymb = 14, Msg3start = 0;
915 916
  ra->Msg3_tda_id = 16; // initialization to a value above limit

917
  NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = ul_bwp->tdaList_Common;
918

919 920
  const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
  const int n_slots_frame = nr_slots_per_frame[mu];
921
  uint8_t k2 = 0;
922
  if (frame_type == TDD) {
923
    int msg3_slot = get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols);
924 925 926 927 928 929 930
    if (tdd->nrofUplinkSymbols != 0) {
      if (tdd->nrofUplinkSymbols < 3)
        msg3_slot++; // we can't trasmit msg3 in mixed slot if there are less than 3 symbols
      else {
        Msg3maxsymb = tdd->nrofUplinkSymbols;
        Msg3start = 14 - tdd->nrofUplinkSymbols;
      }
Raymond Knopp's avatar
Raymond Knopp committed
931
    }
932 933
    const int nb_periods_per_frame = get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
    const int nb_slots_per_period = ((1<<mu)*10)/nb_periods_per_frame;
934
    for (int i=0; i<pusch_TimeDomainAllocationList->list.count; i++) {
935 936
      startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[i]->startSymbolAndLength;
      SLIV2SL(startSymbolAndLength, &StartSymbolIndex, &NrOfSymbols);
937
      k2 = *pusch_TimeDomainAllocationList->list.array[i]->k2;
Raymond Knopp's avatar
Raymond Knopp committed
938 939
      LOG_D(NR_MAC,"Checking Msg3 TDA %d for Msg3_slot %d Msg3_start %d Msg3_nsymb %d: k2 %d, sliv %d,S %d L %d\n",
            i, msg3_slot, Msg3start, Msg3maxsymb, (int)k2, (int)pusch_TimeDomainAllocationList->list.array[i]->startSymbolAndLength, StartSymbolIndex, NrOfSymbols);
940
      // we want to transmit in the uplink symbols of mixed slot or the first uplink slot
francescomani's avatar
francescomani committed
941 942
      abs_slot = (current_slot + k2 + DELTA[mu]);
      int temp_slot = abs_slot % nr_slots_per_frame[mu]; // msg3 slot according to 8.3 in 38.213
943
      if ((temp_slot % nb_slots_per_period) == msg3_slot &&
944
          is_xlsch_in_slot(mac->ulsch_slot_bitmap[temp_slot / 64], temp_slot) &&
Raymond Knopp's avatar
Raymond Knopp committed
945 946
          StartSymbolIndex == Msg3start &&
          NrOfSymbols <= Msg3maxsymb) {
947 948 949 950 951
        ra->Msg3_tda_id = i;
        ra->msg3_startsymb = StartSymbolIndex;
        ra->msg3_nrsymb = NrOfSymbols;
        ra->Msg3_slot = temp_slot;
        break;
952
      }
953
    }
954
    AssertFatal(ra->Msg3_tda_id < 16, "Couldn't find an appropriate TD allocation for Msg3\n");
955
  }
956 957 958
  else {
    ra->Msg3_tda_id = 0;
    k2 = *pusch_TimeDomainAllocationList->list.array[0]->k2;
francescomani's avatar
francescomani committed
959 960
    abs_slot = current_slot + k2 + DELTA[mu]; // msg3 slot according to 8.3 in 38.213
    ra->Msg3_slot = abs_slot % nr_slots_per_frame[mu];
961
  }
962

963
  AssertFatal(ra->Msg3_tda_id<16,"Unable to find Msg3 time domain allocation in list\n");
964

francescomani's avatar
francescomani committed
965
  if (n_slots_frame > abs_slot)
966 967
    ra->Msg3_frame = current_frame;
  else
francescomani's avatar
francescomani committed
968
    ra->Msg3_frame = (current_frame + (abs_slot / n_slots_frame)) % 1024;
969

970 971
  // beam association for FR2
  if (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] >= 257) {
972 973
    AssertFatal(tdd,"Dynamic TDD not handled yet\n");
    uint8_t tdd_period_slot = n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
974 975 976 977 978 979 980
    int num_tdd_period = ra->Msg3_slot/tdd_period_slot;
    if((tdd_beam_association[num_tdd_period]!=-1)&&(tdd_beam_association[num_tdd_period]!=ra->beam_id))
      AssertFatal(1==0,"Cannot schedule MSG3\n");
    else
      tdd_beam_association[num_tdd_period] = ra->beam_id;
  }

981
  LOG_I(NR_MAC, "[RAPROC] Msg3 slot %d: current slot %u Msg3 frame %u k2 %u Msg3_tda_id %u\n", ra->Msg3_slot, current_slot, ra->Msg3_frame, k2,ra->Msg3_tda_id);
982 983
  const int buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, mu, mac->vrb_map_UL_size);
  uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[buffer_index * MAX_BWP_SIZE];
984

985 986
  int bwpSize = sc_info->initial_ul_BWPSize;
  int bwpStart = sc_info->initial_ul_BWPStart;
francescomani's avatar
francescomani committed
987 988 989
  if (bwpSize != ul_bwp->BWPSize || bwpStart != ul_bwp->BWPStart) {
    int act_bwp_start = ul_bwp->BWPStart;
    int act_bwp_size  = ul_bwp->BWPSize;
990
    if (!((bwpStart >= act_bwp_start) && ((bwpStart+bwpSize) <= (act_bwp_start+act_bwp_size))))
991 992
      bwpStart = act_bwp_start;
  }
rmagueta's avatar
rmagueta committed
993

994
  /* search msg3_nb_rb free RBs */
995 996
  int rbSize = 0;
  int rbStart = 0;
rmagueta's avatar
rmagueta committed
997
  while (rbSize < msg3_nb_rb) {
998 999
    rbStart += rbSize; /* last iteration rbSize was not enough, skip it */
    rbSize = 0;
1000
    while (rbStart < bwpSize &&
1001
           (vrb_map_UL[rbStart + bwpStart]&SL_to_bitmap(StartSymbolIndex, NrOfSymbols)))
1002
      rbStart++;
rmagueta's avatar
rmagueta committed
1003
    AssertFatal(rbStart < bwpSize - msg3_nb_rb, "no space to allocate Msg 3 for RA!\n");
1004
    while (rbStart + rbSize < bwpSize
1005
           && !(vrb_map_UL[rbStart + bwpStart + rbSize]&SL_to_bitmap(StartSymbolIndex, NrOfSymbols))
rmagueta's avatar
rmagueta committed
1006
           && rbSize < msg3_nb_rb)
1007
      rbSize++;
1008
  }
rmagueta's avatar
rmagueta committed
1009
  ra->msg3_nb_rb = msg3_nb_rb;
1010
  ra->msg3_first_rb = rbStart;
1011
  ra->msg3_bwp_start = bwpStart;
1012 1013
}

1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu,
                                NR_ServingCellConfigCommon_t *scc,
                                int round,
                                int startSymbolAndLength,
                                rnti_t rnti,
                                int scs,
                                int bwp_size,
                                int bwp_start,
                                int mappingtype,
                                int fh,
                                int msg3_first_rb,
                                int msg3_nb_rb)
{
1027
  int start_symbol_index,nr_of_symbols;
1028

1029
  SLIV2SL(startSymbolAndLength, &start_symbol_index, &nr_of_symbols);
1030
  int mcsindex = -1; // init value
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040

  pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA;
  pusch_pdu->rnti = rnti;
  pusch_pdu->handle = 0;
  pusch_pdu->bwp_start = bwp_start;
  pusch_pdu->bwp_size = bwp_size;
  pusch_pdu->subcarrier_spacing = scs;
  pusch_pdu->cyclic_prefix = 0;
  pusch_pdu->mcs_table = 0;
  if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL)
1041 1042 1043 1044 1045 1046 1047 1048
    pusch_pdu->transform_precoding = 1; // disabled
  else {
    pusch_pdu->transform_precoding = 0; // enabled
    pusch_pdu->dfts_ofdm.low_papr_group_number = *scc->physCellId % 30;
    pusch_pdu->dfts_ofdm.low_papr_sequence_number = 0;
    if (scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding)
      AssertFatal(1==0,"Hopping mode is not supported in transform precoding\n");
  }
1049 1050 1051
  pusch_pdu->data_scrambling_id = *scc->physCellId;
  pusch_pdu->nrOfLayers = 1;
  pusch_pdu->ul_dmrs_symb_pos = get_l_prime(nr_of_symbols,mappingtype,pusch_dmrs_pos2,pusch_len1,start_symbol_index, scc->dmrs_TypeA_Position);
1052
  LOG_D(NR_MAC, "MSG3 start_sym:%d NR Symb:%d mappingtype:%d, ul_dmrs_symb_pos:%x\n", start_symbol_index, nr_of_symbols, mappingtype, pusch_pdu->ul_dmrs_symb_pos);
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
  pusch_pdu->dmrs_config_type = 0;
  pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; //If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id.
  pusch_pdu->scid = 0; //DMRS sequence initialization [TS38.211, sec 6.4.1.1.1]. Should match what is sent in DCI 0_1, otherwise set to 0.
  pusch_pdu->dmrs_ports = 1;  // 6.2.2 in 38.214 only port 0 to be used
  pusch_pdu->num_dmrs_cdm_grps_no_data = 2;  // no data in dmrs symbols as in 6.2.2 in 38.214
  pusch_pdu->resource_alloc = 1; //type 1
  pusch_pdu->rb_start = msg3_first_rb;
  if (msg3_nb_rb > pusch_pdu->bwp_size)
    AssertFatal(1==0,"MSG3 allocated number of RBs exceed the BWP size\n");
  else
    pusch_pdu->rb_size = msg3_nb_rb;
  pusch_pdu->vrb_to_prb_mapping = 0;

  pusch_pdu->frequency_hopping = fh;
1067 1068 1069 1070
  //pusch_pdu->tx_direct_current_location;
  //The uplink Tx Direct Current location for the carrier. Only values in the value range of this field between 0 and 3299,
  //which indicate the subcarrier index within the carrier corresponding 1o the numerology of the corresponding uplink BWP and value 3300,
  //which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE]
1071 1072 1073 1074 1075
  pusch_pdu->uplink_frequency_shift_7p5khz = 0;
  //Resource Allocation in time domain
  pusch_pdu->start_symbol_index = start_symbol_index;
  pusch_pdu->nr_of_symbols = nr_of_symbols;
  //Optional Data only included if indicated in pduBitmap
1076
  pusch_pdu->pusch_data.rv_index = nr_rv_round_map[round%4];
1077
  pusch_pdu->pusch_data.harq_process_id = 0;
1078
  pusch_pdu->pusch_data.new_data_indicator = (round == 0) ? 1 : 0;;
1079
  pusch_pdu->pusch_data.num_cb = 0;
francescomani's avatar
francescomani committed
1080 1081 1082
  int num_dmrs_symb = 0;
  for(int i = start_symbol_index; i < start_symbol_index+nr_of_symbols; i++)
    num_dmrs_symb += (pusch_pdu->ul_dmrs_symb_pos >> i) & 1;
1083 1084 1085
  int TBS = 0;
  while(TBS<7) {  // TBS for msg3 is 7 bytes (except for RRCResumeRequest1 currently not implemented)
    mcsindex++;
1086
    AssertFatal(mcsindex<28,"Exceeding MCS limit for Msg3\n");
francescomani's avatar
francescomani committed
1087 1088
    int R = nr_get_code_rate_ul(mcsindex,pusch_pdu->mcs_table);
    pusch_pdu->target_code_rate = R;
1089 1090
    pusch_pdu->qam_mod_order = nr_get_Qm_ul(mcsindex,pusch_pdu->mcs_table);
    TBS = nr_compute_tbs(pusch_pdu->qam_mod_order,
1091
                         R,
1092 1093 1094 1095 1096 1097 1098 1099 1100
                         pusch_pdu->rb_size,
                         pusch_pdu->nr_of_symbols,
                         num_dmrs_symb*12, // nb dmrs set for no data in dmrs symbol
                         0, //nb_rb_oh
                         0, // to verify tb scaling
                         pusch_pdu->nrOfLayers)>>3;

    pusch_pdu->mcs_index = mcsindex;
    pusch_pdu->pusch_data.tb_size = TBS;
1101
    pusch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS<<3,R);
1102
  }
1103 1104
}

1105
static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra, uint8_t *RAR_pdu)
1106
{
1107 1108 1109
  gNB_MAC_INST *mac = RC.nrmac[module_idP];
  NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
francescomani's avatar
francescomani committed
1110
  NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP;
1111
  NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info;
cig's avatar
cig committed
1112

1113
  if (ra->state == RA_IDLE) {
1114
    LOG_W(NR_MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", ra->rnti);
1115 1116
    return;
  }
cig's avatar
cig committed
1117

1118
  const int scs = ul_bwp->scs;
luis_pereira87's avatar
luis_pereira87 committed
1119
  const uint16_t mask = SL_to_bitmap(ra->msg3_startsymb, ra->msg3_nrsymb);
1120 1121
  int buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, scs, mac->vrb_map_UL_size);
  uint16_t *vrb_map_UL = &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[buffer_index * MAX_BWP_SIZE];
1122
  for (int i = 0; i < ra->msg3_nb_rb; ++i) {
1123
    AssertFatal(!(vrb_map_UL[i + ra->msg3_first_rb + ra->msg3_bwp_start] & mask),
1124 1125 1126 1127
                "RB %d in %4d.%2d is already taken, cannot allocate Msg3!\n",
                i + ra->msg3_first_rb,
                ra->Msg3_frame,
                ra->Msg3_slot);
1128
    vrb_map_UL[i + ra->msg3_first_rb + ra->msg3_bwp_start] |= mask;
1129 1130
  }

1131
  LOG_D(NR_MAC, "[gNB %d][RAPROC] Frame %d, Slot %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", module_idP, frameP, slotP, CC_id, ra->Msg3_frame, ra->Msg3_slot);
1132 1133
  buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, scs, mac->UL_tti_req_ahead_size);
  nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[CC_id][buffer_index];
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
  AssertFatal(future_ul_tti_req->SFN == ra->Msg3_frame
              && future_ul_tti_req->Slot == ra->Msg3_slot,
              "future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n",
              future_ul_tti_req->SFN,
              future_ul_tti_req->Slot,
              ra->Msg3_frame,
              ra->Msg3_slot);
  future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE;
  future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t);
  nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu;
cig's avatar
cig committed
1144
  memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t));
1145

1146
  const int ibwp_size = sc_info->initial_ul_BWPSize;
francescomani's avatar
francescomani committed
1147
  const int fh = (ul_bwp->pusch_Config && ul_bwp->pusch_Config->frequencyHopping) ? 1 : 0;
1148 1149
  const int startSymbolAndLength = ul_bwp->tdaList_Common->list.array[ra->Msg3_tda_id]->startSymbolAndLength;
  const int mappingtype = ul_bwp->tdaList_Common->list.array[ra->Msg3_tda_id]->mappingType;
1150

1151
  LOG_D(NR_MAC, "Frame %d, Slot %d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d,%d) for rnti: %d\n",
cig's avatar
cig committed
1152 1153 1154 1155 1156 1157 1158 1159 1160
    frameP,
    slotP,
    ra->Msg3_frame,
    ra->Msg3_slot,
    ra->msg3_nb_rb,
    ra->msg3_first_rb,
    ra->msg3_round,
    ra->rnti);

1161
  fill_msg3_pusch_pdu(pusch_pdu,scc,
1162
                      ra->msg3_round,
1163 1164
                      startSymbolAndLength,
                      ra->rnti, scs,
1165
                      ibwp_size, ra->msg3_bwp_start,
1166 1167 1168
                      mappingtype, fh,
                      ra->msg3_first_rb, ra->msg3_nb_rb);
  future_ul_tti_req->n_pdus += 1;
1169 1170

  // calling function to fill rar message
1171
  nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu);
cig's avatar
cig committed
1172 1173
}

1174 1175 1176 1177 1178 1179 1180 1181

static void nr_generate_Msg2(module_id_t module_idP,
                             int CC_id,
                             frame_t frameP,
                             sub_frame_t slotP,
                             NR_RA_t *ra,
                             nfapi_nr_dl_tti_request_t *DL_req,
                             nfapi_nr_tx_data_request_t *TX_req)
1182
{
rmagueta's avatar
rmagueta committed
1183 1184
  gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
  NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
francescomani's avatar
francescomani committed
1185
  NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP;
1186
  NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info;
1187

rmagueta's avatar
rmagueta committed
1188
  if ((ra->Msg2_frame == frameP) && (ra->Msg2_slot == slotP)) {
1189

1190
    int mcsIndex = -1;  // initialization value
1191
    int rbStart = 0;
1192
    int rbSize = 8;
cig's avatar
cig committed
1193

rmagueta's avatar
rmagueta committed
1194
    NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
1195
    NR_SearchSpace_t *ss = ra->ra_ss;
1196

rmagueta's avatar
rmagueta committed
1197 1198 1199
    long BWPStart = 0;
    long BWPSize = 0;
    NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL;
1200
    if(*ss->controlResourceSetId != 0) {
francescomani's avatar
francescomani committed
1201
      BWPStart = dl_bwp->BWPStart;
1202
      BWPSize = sc_info->initial_dl_BWPSize;
rmagueta's avatar
rmagueta committed
1203 1204 1205 1206 1207
    } else {
      type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[ra->beam_id];
      BWPStart = type0_PDCCH_CSS_config->cset_start_rb;
      BWPSize = type0_PDCCH_CSS_config->num_rbs;
    }
1208

1209
    NR_ControlResourceSet_t *coreset = ra->coreset;
1210
    AssertFatal(coreset != NULL,"Coreset cannot be null for RA-Msg2\n");
1211
    const int coresetid = coreset->controlResourceSetId;
1212
    // Calculate number of symbols
francescomani's avatar
francescomani committed
1213
    int time_domain_assignment = get_dl_tda(nr_mac, scc, slotP);
1214
    int mux_pattern = type0_PDCCH_CSS_config ? type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern : 1;
1215 1216 1217 1218 1219 1220 1221 1222
    NR_tda_info_t tda_info = get_dl_tda_info(dl_bwp,
                                             ss->searchSpaceType->present,
                                             time_domain_assignment,
                                             scc->dmrs_TypeA_Position,
                                             mux_pattern,
                                             TYPE_RA_RNTI_,
                                             coresetid,
                                             false);
cig's avatar
cig committed
1223

1224
    uint16_t *vrb_map = cc[CC_id].vrb_map;
1225
    for (int i = 0; (i < rbSize) && (rbStart <= (BWPSize - rbSize)); i++) {
francescomani's avatar
francescomani committed
1226
      if (vrb_map[BWPStart + rbStart + i]&SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)) {
1227 1228 1229 1230
        rbStart += i;
        i = 0;
      }
    }
rmagueta's avatar
rmagueta committed
1231

1232
    if (rbStart > (BWPSize - rbSize)) {
rmagueta's avatar
rmagueta committed
1233
      LOG_E(NR_MAC, "%s(): cannot find free vrb_map for RA RNTI %04x!\n", __func__, ra->RA_rnti);
1234 1235 1236
      return;
    }

1237
    // Checking if the DCI allocation is feasible in current subframe
1238
    nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
1239
    if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) {
1240
      LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, ra->RA_rnti);
1241 1242 1243
      return;
    }

rmagueta's avatar
rmagueta committed
1244
    uint8_t aggregation_level;
1245 1246 1247 1248 1249 1250 1251
    int CCEIndex = get_cce_index(nr_mac,
                                 CC_id, slotP, 0,
                                 &aggregation_level,
                                 ss,
                                 coreset,
                                 &ra->sched_pdcch,
                                 true);
1252

1253
    if (CCEIndex < 0) {
1254
      LOG_E(NR_MAC, "cannot find free CCE for Msg2 of RA RNTI 0x%04x!\n", ra->rnti);
1255
      nr_clear_ra_proc(module_idP, CC_id, frameP, ra);
1256 1257 1258
      return;
    }

francescomani's avatar
francescomani committed
1259
    LOG_D(NR_MAC,"Msg2 startSymbolIndex.nrOfSymbols %d.%d\n",tda_info.startSymbolIndex,tda_info.nrOfSymbols);
rmagueta's avatar
rmagueta committed
1260

rmagueta's avatar
rmagueta committed
1261 1262
    // look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it. This is especially
    // important if we have multiple RAs, and the DLSCH has to reuse them, so we need to mark them
1263
    nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][coresetid];
1264 1265 1266 1267 1268 1269 1270
    if (!pdcch_pdu_rel15) {
      nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
      memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t));
      dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
      dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu));
      dl_req->nPDUs += 1;
      pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
1271
      nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch);
1272
      nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15;
1273
    }
cig's avatar
cig committed
1274

1275
    nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
cig's avatar
cig committed
1276 1277 1278
    memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
    dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
    dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
1279
    dl_req->nPDUs+=1;
cig's avatar
cig committed
1280
    nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
1281

1282
    LOG_A(NR_MAC,"[gNB %d][RAPROC] CC_id %d Frame %d, slotP %d: Generating RA-Msg2 DCI, rnti 0x%x, state %d, CoreSetType %d\n",
Eurecom's avatar
Eurecom committed
1283
          module_idP, CC_id, frameP, slotP, ra->RA_rnti, ra->state,pdcch_pdu_rel15->CoreSetType);
cig's avatar
cig committed
1284

rmagueta's avatar
rmagueta committed
1285 1286
    // SCF222: PDU index incremented for each PDSCH PDU sent in TX control message. This is used to associate control
    // information to data and is reset every slot.
1287
    const int pduindex = nr_mac->pdu_index[CC_id]++;
francescomani's avatar
francescomani committed
1288
    uint8_t mcsTableIdx = dl_bwp->mcsTableIdx;
1289

francescomani's avatar
francescomani committed
1290 1291 1292 1293
   NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc,
                                                   dl_bwp,
                                                   &tda_info,
                                                   1);
1294

rmagueta's avatar
rmagueta committed
1295 1296
    pdsch_pdu_rel15->pduBitmap = 0;
    pdsch_pdu_rel15->rnti = ra->RA_rnti;
1297
    pdsch_pdu_rel15->pduIndex = pduindex;
1298 1299
    pdsch_pdu_rel15->BWPSize  = BWPSize;
    pdsch_pdu_rel15->BWPStart = BWPStart;
francescomani's avatar
francescomani committed
1300
    pdsch_pdu_rel15->SubcarrierSpacing = dl_bwp->scs;
cig's avatar
cig committed
1301 1302
    pdsch_pdu_rel15->CyclicPrefix = 0;
    pdsch_pdu_rel15->NrOfCodewords = 1;
rmagueta's avatar
rmagueta committed
1303
    pdsch_pdu_rel15->mcsTable[0] = mcsTableIdx;
cig's avatar
cig committed
1304 1305 1306 1307 1308
    pdsch_pdu_rel15->rvIndex[0] = 0;
    pdsch_pdu_rel15->dataScramblingId = *scc->physCellId;
    pdsch_pdu_rel15->nrOfLayers = 1;
    pdsch_pdu_rel15->transmissionScheme = 0;
    pdsch_pdu_rel15->refPoint = 0;
francescomani's avatar
francescomani committed
1309
    pdsch_pdu_rel15->dmrsConfigType = dmrs_parms.dmrsConfigType;
cig's avatar
cig committed
1310 1311
    pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId;
    pdsch_pdu_rel15->SCID = 0;
francescomani's avatar
francescomani committed
1312
    pdsch_pdu_rel15->numDmrsCdmGrpsNoData = dmrs_parms.numDmrsCdmGrpsNoData;
cig's avatar
cig committed
1313 1314
    pdsch_pdu_rel15->dmrsPorts = 1;
    pdsch_pdu_rel15->resourceAlloc = 1;
1315 1316
    pdsch_pdu_rel15->rbStart = rbStart;
    pdsch_pdu_rel15->rbSize = rbSize;
rmagueta's avatar
rmagueta committed
1317
    pdsch_pdu_rel15->VRBtoPRBMapping = 0;
francescomani's avatar
francescomani committed
1318 1319 1320
    pdsch_pdu_rel15->StartSymbolIndex = tda_info.startSymbolIndex;
    pdsch_pdu_rel15->NrOfSymbols = tda_info.nrOfSymbols;
    pdsch_pdu_rel15->dlDmrsSymbPos = dmrs_parms.dl_dmrs_symb_pos;
cig's avatar
cig committed
1321

rmagueta's avatar
rmagueta committed
1322
    uint8_t tb_scaling = 0;
1323 1324 1325 1326 1327 1328 1329 1330 1331 1332
    int R, Qm;
    uint32_t TBS=0;

    while(TBS<9) {  // min TBS for RAR is 9 bytes
      mcsIndex++;
      R = nr_get_code_rate_dl(mcsIndex, mcsTableIdx);
      Qm = nr_get_Qm_dl(mcsIndex, mcsTableIdx);
      TBS = nr_compute_tbs(Qm,
                           R,
                           rbSize,
francescomani's avatar
francescomani committed
1333 1334
                           tda_info.nrOfSymbols,
                           dmrs_parms.N_PRB_DMRS*dmrs_parms.N_DMRS_SLOT,
1335 1336 1337 1338 1339 1340 1341 1342 1343
                           0, // overhead
                           tb_scaling,  // tb scaling
		           1)>>3;  // layers

      pdsch_pdu_rel15->targetCodeRate[0] = R;
      pdsch_pdu_rel15->qamModOrder[0] = Qm;
      pdsch_pdu_rel15->mcsIndex[0] = mcsIndex;
      pdsch_pdu_rel15->TBSize[0] = TBS;
    }
cig's avatar
cig committed
1344

1345
    pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(mcsTableIdx, sc_info->dl_bw_tbslbrm, 1);
1346
    pdsch_pdu_rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS<<3,R);
1347

rmagueta's avatar
rmagueta committed
1348
    // Fill PDCCH DL DCI PDU
1349 1350
    nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci];
    pdcch_pdu_rel15->numDlDci++;
rmagueta's avatar
rmagueta committed
1351
    dci_pdu->RNTI = ra->RA_rnti;
1352 1353 1354 1355 1356 1357 1358 1359 1360
    dci_pdu->ScramblingId = *scc->physCellId;
    dci_pdu->ScramblingRNTI = 0;
    dci_pdu->AggregationLevel = aggregation_level;
    dci_pdu->CceIndex = CCEIndex;
    dci_pdu->beta_PDCCH_1_0 = 0;
    dci_pdu->powerControlOffsetSS = 1;

    dci_pdu_rel15_t dci_payload;
    dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize,
rmagueta's avatar
rmagueta committed
1361
                                                                                    pdsch_pdu_rel15->rbStart,
rmagueta's avatar
rmagueta committed
1362
                                                                                    BWPSize);
1363

rmagueta's avatar
rmagueta committed
1364
    LOG_D(NR_MAC,"Msg2 rbSize.rbStart.BWPsize %d.%d.%ld\n",pdsch_pdu_rel15->rbSize,
1365
          pdsch_pdu_rel15->rbStart,
rmagueta's avatar
rmagueta committed
1366
          BWPSize);
rmagueta's avatar
rmagueta committed
1367

1368 1369 1370
    dci_payload.time_domain_assignment.val = time_domain_assignment;
    dci_payload.vrb_to_prb_mapping.val = 0;
    dci_payload.mcs = pdsch_pdu_rel15->mcsIndex[0];
rmagueta's avatar
rmagueta committed
1371
    dci_payload.tb_scaling = tb_scaling;
1372

Abhijith's avatar
Abhijith committed
1373
    LOG_D(NR_MAC,
rmagueta's avatar
rmagueta committed
1374
          "[RAPROC] DCI type 1 payload: freq_alloc %d (%d,%d,%ld), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d \n",
1375
          dci_payload.frequency_domain_assignment.val,
1376 1377
          pdsch_pdu_rel15->rbStart,
          pdsch_pdu_rel15->rbSize,
rmagueta's avatar
rmagueta committed
1378
          BWPSize,
1379 1380 1381 1382
          dci_payload.time_domain_assignment.val,
          dci_payload.vrb_to_prb_mapping.val,
          dci_payload.mcs,
          dci_payload.tb_scaling);
cig's avatar
cig committed
1383

Abhijith's avatar
Abhijith committed
1384
    LOG_D(NR_MAC,
1385 1386
          "[RAPROC] DCI params: rnti 0x%x, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d  "
          "n_symb %d\n",
1387
          pdcch_pdu_rel15->dci_pdu[0].RNTI,
1388
          TYPE_RA_RNTI_,
rmagueta's avatar
rmagueta committed
1389
          NR_DL_DCI_FORMAT_1_0,
1390
          *(unsigned long long *)pdcch_pdu_rel15->FreqDomainResource,
1391 1392
          pdcch_pdu_rel15->StartSymbolIndex,
          pdcch_pdu_rel15->DurationSymbols);
cig's avatar
cig committed
1393

1394
    fill_dci_pdu_rel15(sc_info,
francescomani's avatar
francescomani committed
1395
                       dl_bwp,
1396
                       &ra->UL_BWP,
rmagueta's avatar
rmagueta committed
1397
                       &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1],
1398
                       &dci_payload,
rmagueta's avatar
rmagueta committed
1399
                       NR_DL_DCI_FORMAT_1_0,
1400
                       TYPE_RA_RNTI_,
francescomani's avatar
francescomani committed
1401
                       dl_bwp->bwp_id,
1402
                       ss,
1403
                       coreset,
1404
                       0, // parameter not needed for DCI 1_0
1405
                       nr_mac->cset0_bwp_size);
cig's avatar
cig committed
1406 1407

    // DL TX request
1408
    nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs];
rmagueta's avatar
rmagueta committed
1409 1410

    // Program UL processing for Msg3
francescomani's avatar
francescomani committed
1411
    nr_get_Msg3alloc(module_idP, CC_id, scc, slotP, frameP, ra, nr_mac->tdd_beam_association);
rmagueta's avatar
rmagueta committed
1412 1413
    nr_add_msg3(module_idP, CC_id, frameP, slotP, ra, (uint8_t *) &tx_req->TLVs[0].value.direct[0]);

1414 1415 1416 1417 1418 1419 1420 1421
    // Start RA contention resolution timer in Msg3 transmission slot (current slot + K2)
    // 3GPP TS 38.321 Section 5.1.5 Contention Resolution
    start_ra_contention_resolution_timer(
        ra,
        scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer,
        *ra->UL_BWP.tdaList_Common->list.array[ra->Msg3_tda_id]->k2,
        ra->UL_BWP.scs);

1422 1423 1424 1425 1426 1427 1428 1429
    if (ra->cfra) {
      NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_idP]->UE_info, ra->rnti);
      if (UE) {
        const NR_ServingCellConfig_t *servingCellConfig = UE->CellGroup ? UE->CellGroup->spCellConfig->spCellConfigDedicated : NULL;
        uint32_t delay_ms = servingCellConfig && servingCellConfig->downlinkBWP_ToAddModList ? NR_RRC_SETUP_DELAY_MS + NR_RRC_BWP_SWITCHING_DELAY_MS : NR_RRC_SETUP_DELAY_MS;
        NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
        sched_ctrl->rrc_processing_timer = (delay_ms << ra->DL_BWP.scs);
      }
1430
      LOG_D(NR_MAC, "Frame %d, Subframe %d: Setting RA-Msg3 reception (CFRA) for SFN.Slot %d.%d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot);
1431 1432
    } else {
      LOG_D(NR_MAC, "Frame %d, Subframe %d: Setting RA-Msg3 reception (CBRA) for SFN.Slot %d.%d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot);
1433
    }
rmagueta's avatar
rmagueta committed
1434 1435 1436 1437

    T(T_GNB_MAC_DL_RAR_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(ra->RA_rnti), T_INT(frameP),
      T_INT(slotP), T_INT(0), T_BUFFER(&tx_req->TLVs[0].value.direct[0], tx_req->TLVs[0].length));

1438
    tx_req->PDU_index = pduindex;
cig's avatar
cig committed
1439
    tx_req->num_TLV = 1;
1440 1441
    tx_req->TLVs[0].length = pdsch_pdu_rel15->TBSize[0];
    tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, pdsch_pdu_rel15->TBSize[0]);
1442 1443 1444
    TX_req->SFN = frameP;
    TX_req->Number_of_PDUs++;
    TX_req->Slot = slotP;
1445

1446
    // Mark the corresponding symbols RBs as used
1447 1448
    fill_pdcch_vrb_map(nr_mac,
                       CC_id,
1449
                       &ra->sched_pdcch,
1450 1451
                       CCEIndex,
                       aggregation_level);
1452
    for (int rb = 0; rb < rbSize; rb++) {
francescomani's avatar
francescomani committed
1453
      vrb_map[BWPStart + rb + rbStart] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
rmagueta's avatar
rmagueta committed
1454
    }
rmagueta's avatar
rmagueta committed
1455 1456

    ra->state = WAIT_Msg3;
1457
    LOG_D(NR_MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: rnti %04x RA state %d\n", module_idP, frameP, slotP, ra->rnti, ra->state);
cig's avatar
cig committed
1458
  }
1459 1460
}

1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
static void prepare_dl_pdus(gNB_MAC_INST *nr_mac,
                            NR_RA_t *ra,
                            NR_UE_DL_BWP_t *dl_bwp,
                            nfapi_nr_dl_tti_request_body_t *dl_req,
                            NR_sched_pucch_t *pucch,
                            NR_pdsch_dmrs_t dmrs_info,
                            NR_tda_info_t tda,
                            int aggregation_level,
                            int CCEIndex,
                            int tb_size,
                            int ndi,
                            int tpc,
                            int delta_PRI,
                            int current_harq_pid,
                            int time_domain_assignment,
                            int CC_id,
                            int rnti,
                            int round,
                            int mcsIndex,
                            int tb_scaling,
                            int pduindex,
                            int rbStart,
                            int rbSize)
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496
{
  // look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it. This is especially
  // important if we have multiple RAs, and the DLSCH has to reuse them, so we need to mark them
  NR_ControlResourceSet_t *coreset = ra->coreset;
  const int coresetid = coreset->controlResourceSetId;
  nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][coresetid];
  if (!pdcch_pdu_rel15) {
    nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
    memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t));
    dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
    dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu));
    dl_req->nPDUs += 1;
    pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
1497
    nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch);
1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560
    nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15;
  }

  nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
  memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
  dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
  dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
  dl_req->nPDUs+=1;
  nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;

  NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;

  long BWPStart = 0;
  long BWPSize = 0;
  NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL;
  NR_SearchSpace_t *ss = ra->ra_ss;
  if(*ss->controlResourceSetId!=0) {
    BWPStart = dl_bwp->BWPStart;
    BWPSize  = dl_bwp->BWPSize;
  } else {
    type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[ra->beam_id];
    BWPStart = type0_PDCCH_CSS_config->cset_start_rb;
    BWPSize = type0_PDCCH_CSS_config->num_rbs;
  }

  int mcsTableIdx = dl_bwp->mcsTableIdx;

  pdsch_pdu_rel15->pduBitmap = 0;
  pdsch_pdu_rel15->rnti = rnti;
  pdsch_pdu_rel15->pduIndex = pduindex;
  pdsch_pdu_rel15->BWPSize  = BWPSize;
  pdsch_pdu_rel15->BWPStart = BWPStart;
  pdsch_pdu_rel15->SubcarrierSpacing = dl_bwp->scs;
  pdsch_pdu_rel15->CyclicPrefix = 0;
  pdsch_pdu_rel15->NrOfCodewords = 1;
  int R = nr_get_code_rate_dl(mcsIndex,mcsTableIdx);
  pdsch_pdu_rel15->targetCodeRate[0] = R;
  int Qm = nr_get_Qm_dl(mcsIndex, mcsTableIdx);
  pdsch_pdu_rel15->qamModOrder[0] = Qm;
  pdsch_pdu_rel15->mcsIndex[0] = mcsIndex;
  pdsch_pdu_rel15->mcsTable[0] = mcsTableIdx;
  pdsch_pdu_rel15->rvIndex[0] = nr_rv_round_map[round % 4];
  pdsch_pdu_rel15->dataScramblingId = *scc->physCellId;
  pdsch_pdu_rel15->nrOfLayers = 1;
  pdsch_pdu_rel15->transmissionScheme = 0;
  pdsch_pdu_rel15->refPoint = 0;
  pdsch_pdu_rel15->dmrsConfigType = dmrs_info.dmrsConfigType;
  pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId;
  pdsch_pdu_rel15->SCID = 0;
  pdsch_pdu_rel15->numDmrsCdmGrpsNoData = dmrs_info.numDmrsCdmGrpsNoData;
  pdsch_pdu_rel15->dmrsPorts = 1;
  pdsch_pdu_rel15->resourceAlloc = 1;
  pdsch_pdu_rel15->rbStart = rbStart;
  pdsch_pdu_rel15->rbSize = rbSize;
  pdsch_pdu_rel15->VRBtoPRBMapping = 0;
  pdsch_pdu_rel15->StartSymbolIndex = tda.startSymbolIndex;
  pdsch_pdu_rel15->NrOfSymbols = tda.nrOfSymbols;
  pdsch_pdu_rel15->dlDmrsSymbPos = dmrs_info.dl_dmrs_symb_pos;

  int x_Overhead = 0;
  nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, tb_scaling);

1561
  pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(mcsTableIdx, ra->sc_info.dl_bw_tbslbrm, 1);
1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612
  pdsch_pdu_rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(tb_size<<3,R);

  pdsch_pdu_rel15->precodingAndBeamforming.num_prgs=1;
  pdsch_pdu_rel15->precodingAndBeamforming.prg_size=275;
  pdsch_pdu_rel15->precodingAndBeamforming.dig_bf_interfaces=1;
  pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].pm_idx = 0;
  pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = ra->beam_id;

  /* Fill PDCCH DL DCI PDU */
  nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci];
  pdcch_pdu_rel15->numDlDci++;
  dci_pdu->RNTI = rnti;
  dci_pdu->ScramblingId = *scc->physCellId;
  dci_pdu->ScramblingRNTI = 0;
  dci_pdu->AggregationLevel = aggregation_level;
  dci_pdu->CceIndex = CCEIndex;
  dci_pdu->beta_PDCCH_1_0 = 0;
  dci_pdu->powerControlOffsetSS = 1;

  dci_pdu_rel15_t dci_payload;
  dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize,
                                                                                  pdsch_pdu_rel15->rbStart,
                                                                                  BWPSize);

  dci_payload.format_indicator = 1;
  dci_payload.time_domain_assignment.val = time_domain_assignment;
  dci_payload.vrb_to_prb_mapping.val = 0;
  dci_payload.mcs = pdsch_pdu_rel15->mcsIndex[0];
  dci_payload.tb_scaling = tb_scaling;
  dci_payload.rv = pdsch_pdu_rel15->rvIndex[0];
  dci_payload.harq_pid = current_harq_pid;
  dci_payload.ndi = ndi;
  dci_payload.dai[0].val = pucch ? (pucch->dai_c-1) & 3 : 0;
  dci_payload.tpc = tpc; // TPC for PUCCH: table 7.2.1-1 in 38.213
  dci_payload.pucch_resource_indicator = delta_PRI; // This is delta_PRI from 9.2.1 in 38.213
  dci_payload.pdsch_to_harq_feedback_timing_indicator.val = pucch ? pucch->timing_indicator : 0;

  LOG_D(NR_MAC,
        "[RAPROC] DCI 1_0 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d pucchres %d harqtiming %d\n",
        dci_payload.frequency_domain_assignment.val,
        pdsch_pdu_rel15->rbStart,
        pdsch_pdu_rel15->rbSize,
        pdsch_pdu_rel15->BWPSize,
        dci_payload.time_domain_assignment.val,
        dci_payload.vrb_to_prb_mapping.val,
        dci_payload.mcs,
        dci_payload.tb_scaling,
        dci_payload.pucch_resource_indicator,
        dci_payload.pdsch_to_harq_feedback_timing_indicator.val);

  LOG_D(NR_MAC,
1613 1614
        "[RAPROC] DCI params: rnti 0x%x, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d  "
        "n_symb %d, BWPsize %d\n",
1615
        pdcch_pdu_rel15->dci_pdu[0].RNTI,
1616
        TYPE_TC_RNTI_,
1617 1618 1619 1620 1621 1622
        NR_DL_DCI_FORMAT_1_0,
        (unsigned long long)pdcch_pdu_rel15->FreqDomainResource,
        pdcch_pdu_rel15->StartSymbolIndex,
        pdcch_pdu_rel15->DurationSymbols,
        pdsch_pdu_rel15->BWPSize);

1623
  fill_dci_pdu_rel15(&ra->sc_info,
1624 1625 1626 1627 1628
                     dl_bwp,
                     &ra->UL_BWP,
                     &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1],
                     &dci_payload,
                     NR_DL_DCI_FORMAT_1_0,
1629
                     TYPE_TC_RNTI_,
1630 1631 1632
                     dl_bwp->bwp_id,
                     ss,
                     coreset,
1633
                     0, // parameter not needed for DCI 1_0
1634 1635
                     nr_mac->cset0_bwp_size);

1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650
  LOG_D(NR_MAC, "BWPSize: %i\n", pdcch_pdu_rel15->BWPSize);
  LOG_D(NR_MAC, "BWPStart: %i\n", pdcch_pdu_rel15->BWPStart);
  LOG_D(NR_MAC, "SubcarrierSpacing: %i\n", pdcch_pdu_rel15->SubcarrierSpacing);
  LOG_D(NR_MAC, "CyclicPrefix: %i\n", pdcch_pdu_rel15->CyclicPrefix);
  LOG_D(NR_MAC, "StartSymbolIndex: %i\n", pdcch_pdu_rel15->StartSymbolIndex);
  LOG_D(NR_MAC, "DurationSymbols: %i\n", pdcch_pdu_rel15->DurationSymbols);
  for (int n = 0; n < 6; n++)
    LOG_D(NR_MAC, "FreqDomainResource[%i]: %x\n", n, pdcch_pdu_rel15->FreqDomainResource[n]);
  LOG_D(NR_MAC, "CceRegMappingType: %i\n", pdcch_pdu_rel15->CceRegMappingType);
  LOG_D(NR_MAC, "RegBundleSize: %i\n", pdcch_pdu_rel15->RegBundleSize);
  LOG_D(NR_MAC, "InterleaverSize: %i\n", pdcch_pdu_rel15->InterleaverSize);
  LOG_D(NR_MAC, "CoreSetType: %i\n", pdcch_pdu_rel15->CoreSetType);
  LOG_D(NR_MAC, "ShiftIndex: %i\n", pdcch_pdu_rel15->ShiftIndex);
  LOG_D(NR_MAC, "precoderGranularity: %i\n", pdcch_pdu_rel15->precoderGranularity);
  LOG_D(NR_MAC, "numDlDci: %i\n", pdcch_pdu_rel15->numDlDci);
1651 1652
}

1653 1654 1655 1656 1657 1658 1659
static void nr_generate_Msg4(module_id_t module_idP,
                             int CC_id,
                             frame_t frameP,
                             sub_frame_t slotP,
                             NR_RA_t *ra,
                             nfapi_nr_dl_tti_request_t *DL_req,
                             nfapi_nr_tx_data_request_t *TX_req)
1660
{
1661 1662
  gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
  NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
francescomani's avatar
francescomani committed
1663
  NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP;
1664

1665
  // if it is a DL slot, if the RA is in MSG4 state
1666
  if (is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) {
1667

1668 1669 1670
    NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
    NR_SearchSpace_t *ss = ra->ra_ss;

francescomani's avatar
francescomani committed
1671
    NR_ControlResourceSet_t *coreset = ra->coreset;
1672
    AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg4\n");
1673

1674 1675
    uint16_t mac_sdu_length = 0;

1676
    NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, ra->rnti);
Laurent THOMAS's avatar
Laurent THOMAS committed
1677
    if (!UE) {
1678
      LOG_E(NR_MAC, "want to generate Msg4, but rnti %04x not in the table\n", ra->rnti);
1679
      return;
Laurent THOMAS's avatar
Laurent THOMAS committed
1680 1681
    }

1682 1683 1684 1685
    NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
    /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */
    int current_harq_pid = sched_ctrl->retrans_dl_harq.head;

1686
    logical_chan_id_t lcid = DL_SCH_LCID_CCCH;
1687
    if (current_harq_pid < 0) {
1688 1689 1690 1691 1692
      // Check for data on SRB0 (RRCSetup)
      mac_rlc_status_resp_t srb_status = mac_rlc_status_ind(module_idP, ra->rnti, module_idP, frameP, slotP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, 0, 0);

      if (srb_status.bytes_in_buffer == 0) {
        lcid = DL_SCH_LCID_DCCH;
1693
        // Check for data on SRB1 (RRCReestablishment, RRCReconfiguration)
1694 1695 1696 1697 1698 1699 1700
        srb_status = mac_rlc_status_ind(module_idP, ra->rnti, module_idP, frameP, slotP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, 0, 0);
      }

      // Need to wait until data for Msg4 is ready
      if (srb_status.bytes_in_buffer == 0)
        return;
      mac_sdu_length = srb_status.bytes_in_buffer;
1701 1702
    }

rmagueta's avatar
rmagueta committed
1703 1704 1705 1706
    long BWPStart = 0;
    long BWPSize = 0;
    NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL;
    if(*ss->controlResourceSetId!=0) {
francescomani's avatar
francescomani committed
1707 1708
      BWPStart = dl_bwp->BWPStart;
      BWPSize  = dl_bwp->BWPSize;
rmagueta's avatar
rmagueta committed
1709 1710 1711 1712 1713
    } else {
      type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[ra->beam_id];
      BWPStart = type0_PDCCH_CSS_config->cset_start_rb;
      BWPSize = type0_PDCCH_CSS_config->num_rbs;
    }
1714

1715 1716
    // get CCEindex, needed also for PUCCH and then later for PDCCH
    uint8_t aggregation_level;
1717 1718 1719 1720 1721 1722 1723
    int CCEIndex = get_cce_index(nr_mac,
                                 CC_id, slotP, 0,
                                 &aggregation_level,
                                 ss,
                                 coreset,
                                 &ra->sched_pdcch,
                                 true);
1724

1725
    if (CCEIndex < 0) {
1726
      LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI 0x%04x!\n", __func__, ra->rnti);
1727 1728 1729
      return;
    }

1730
    // Checking if the DCI allocation is feasible in current subframe
1731
    nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
1732 1733 1734 1735 1736 1737
    if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) {
      LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, ra->rnti);
      return;
    }

    uint8_t time_domain_assignment = get_dl_tda(nr_mac, scc, slotP);
1738
    int mux_pattern = type0_PDCCH_CSS_config ? type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern : 1;
1739 1740 1741 1742 1743 1744 1745 1746
    NR_tda_info_t msg4_tda = get_dl_tda_info(dl_bwp,
                                             ss->searchSpaceType->present,
                                             time_domain_assignment,
                                             scc->dmrs_TypeA_Position,
                                             mux_pattern,
                                             TYPE_TC_RNTI_,
                                             coreset->controlResourceSetId,
                                             false);
1747

1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758
    NR_pdsch_dmrs_t dmrs_info = get_dl_dmrs_params(scc,
                                                   dl_bwp,
                                                   &msg4_tda,
                                                   1);

    uint8_t mcsTableIdx = dl_bwp->mcsTableIdx;
    uint8_t mcsIndex = 0;
    int rbStart = 0;
    int rbSize = 0;
    uint8_t tb_scaling = 0;
    uint32_t tb_size = 0;
1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769
    uint16_t pdu_length;
    if(current_harq_pid >= 0) { // in case of retransmission
      NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid];
      DevAssert(!harq->is_waiting);
      pdu_length = harq->tb_size;
    }
    else {
      uint8_t subheader_len = (mac_sdu_length < 256) ? sizeof(NR_MAC_SUBHEADER_SHORT) : sizeof(NR_MAC_SUBHEADER_LONG);
      pdu_length = mac_sdu_length + subheader_len + 7; //7 is contetion resolution length
    }

1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784
    // increase PRBs until we get to BWPSize or TBS is bigger than MAC PDU size
    do {
      if(rbSize < BWPSize)
        rbSize++;
      else
        mcsIndex++;
      LOG_D(NR_MAC,"Calling nr_compute_tbs with N_PRB_DMRS %d, N_DMRS_SLOT %d\n",dmrs_info.N_PRB_DMRS,dmrs_info.N_DMRS_SLOT);
      tb_size = nr_compute_tbs(nr_get_Qm_dl(mcsIndex, mcsTableIdx),
                                     nr_get_code_rate_dl(mcsIndex, mcsTableIdx),
                                     rbSize, msg4_tda.nrOfSymbols, dmrs_info.N_PRB_DMRS * dmrs_info.N_DMRS_SLOT, 0, tb_scaling,1) >> 3;
    } while (tb_size < pdu_length && mcsIndex<=28);

    AssertFatal(tb_size >= pdu_length,"Cannot allocate Msg4\n");

    int i = 0;
1785
    uint16_t *vrb_map = cc[CC_id].vrb_map;
1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799
    while ((i < rbSize) && (rbStart + rbSize <= BWPSize)) {
      if (vrb_map[BWPStart + rbStart + i]&SL_to_bitmap(msg4_tda.startSymbolIndex, msg4_tda.nrOfSymbols)) {
        rbStart += i+1;
        i = 0;
      } else {
        i++;
      }
    }

    if (rbStart > (BWPSize - rbSize)) {
      LOG_E(NR_MAC, "%s(): cannot find free vrb_map for RNTI %04x!\n", __func__, ra->rnti);
      return;
    }

1800
    const int delta_PRI = 0;
francescomani's avatar
francescomani committed
1801
    int r_pucch = nr_get_pucch_resource(coreset, ra->UL_BWP.pucch_Config, CCEIndex);
1802

1803
    LOG_D(NR_MAC,"[RAPROC] Msg4 r_pucch %d (CCEIndex %d, delta_PRI %d)\n", r_pucch, CCEIndex, delta_PRI);
1804

francescomani's avatar
francescomani committed
1805
    int alloc = nr_acknack_scheduling(nr_mac, UE, frameP, slotP, r_pucch, 1);
1806
    if (alloc < 0) {
1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822
      LOG_D(NR_MAC,"Couldn't find a pucch allocation for ack nack (msg4) in frame %d slot %d\n",frameP,slotP);
      return;
    }

    // HARQ management
    if (current_harq_pid < 0) {
      AssertFatal(sched_ctrl->available_dl_harq.head >= 0,
                  "UE context not initialized: no HARQ processes found\n");
      current_harq_pid = sched_ctrl->available_dl_harq.head;
      remove_front_nr_list(&sched_ctrl->available_dl_harq);
    }
    NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid];
    DevAssert(!harq->is_waiting);
    add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid);
    harq->is_waiting = true;
    ra->harq_pid = current_harq_pid;
1823
    UE->mac_stats.dl.rounds[harq->round]++;
1824

1825 1826 1827
    NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[alloc];
    harq->feedback_slot = pucch->ul_slot;
    harq->feedback_frame = pucch->frame;
1828
    harq->tb_size = tb_size;
1829

1830
    uint8_t *buf = (uint8_t *) harq->transportBlock;
1831 1832
    // Bytes to be transmitted
    if (harq->round == 0) {
1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856
      // UE Contention Resolution Identity MAC CE
      uint16_t mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, nr_mac->sched_ctrlCommon, buf, 255, ra->cont_res_id);
      LOG_D(NR_MAC,"Encoded contention resolution mac_pdu_length %d\n",mac_pdu_length);
      uint8_t buffer[CCCH_SDU_SIZE];
      uint8_t mac_subheader_len = sizeof(NR_MAC_SUBHEADER_SHORT);
      // Get RLC data on the SRB (RRCSetup, RRCReestablishment)
      mac_sdu_length = mac_rlc_data_req(module_idP,
                                        ra->rnti,
                                        module_idP,
                                        frameP,
                                        ENB_FLAG_YES,
                                        MBMS_FLAG_NO,
                                        lcid,
                                        CCCH_SDU_SIZE,
                                        (char *)buffer,
                                        0,
                                        0);

      if (mac_sdu_length < 256) {
        ((NR_MAC_SUBHEADER_SHORT *)&buf[mac_pdu_length])->R = 0;
        ((NR_MAC_SUBHEADER_SHORT *)&buf[mac_pdu_length])->F = 0;
        ((NR_MAC_SUBHEADER_SHORT *)&buf[mac_pdu_length])->LCID = lcid;
        ((NR_MAC_SUBHEADER_SHORT *)&buf[mac_pdu_length])->L = mac_sdu_length;
        ra->mac_pdu_length = mac_pdu_length + mac_sdu_length + sizeof(NR_MAC_SUBHEADER_SHORT);
1857
      } else {
1858 1859 1860 1861 1862 1863
        mac_subheader_len = sizeof(NR_MAC_SUBHEADER_LONG);
        ((NR_MAC_SUBHEADER_LONG *)&buf[mac_pdu_length])->R = 0;
        ((NR_MAC_SUBHEADER_LONG *)&buf[mac_pdu_length])->F = 1;
        ((NR_MAC_SUBHEADER_LONG *)&buf[mac_pdu_length])->LCID = lcid;
        ((NR_MAC_SUBHEADER_LONG *)&buf[mac_pdu_length])->L = htons(mac_sdu_length);
        ra->mac_pdu_length = mac_pdu_length + mac_sdu_length + sizeof(NR_MAC_SUBHEADER_LONG);
1864
      }
1865
      memcpy(&buf[mac_pdu_length + mac_subheader_len], buffer, mac_sdu_length);
1866
    }
1867

1868
    const int pduindex = nr_mac->pdu_index[CC_id]++;
1869 1870
    prepare_dl_pdus(nr_mac, ra, dl_bwp, dl_req, pucch, dmrs_info, msg4_tda, aggregation_level, CCEIndex, tb_size, harq->ndi, sched_ctrl->tpc1, delta_PRI,
                    current_harq_pid, time_domain_assignment, CC_id, ra->rnti, harq->round, mcsIndex, tb_scaling, pduindex, rbStart, rbSize);
cig's avatar
cig committed
1871

1872
    // Add padding header and zero rest out if there is space left
1873 1874
    if (ra->mac_pdu_length < harq->tb_size) {
      NR_MAC_SUBHEADER_FIXED *padding = (NR_MAC_SUBHEADER_FIXED *) &buf[ra->mac_pdu_length];
1875 1876
      padding->R = 0;
      padding->LCID = DL_SCH_LCID_PADDING;
1877
      for(int k = ra->mac_pdu_length+1; k<harq->tb_size; k++) {
1878 1879 1880 1881
        buf[k] = 0;
      }
    }

1882
    T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(ra->rnti),
1883
      T_INT(frameP), T_INT(slotP), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock, harq->tb_size));
1884

cig's avatar
cig committed
1885
    // DL TX request
1886
    nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs];
1887
    memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock, sizeof(uint8_t) * harq->tb_size);
1888
    tx_req->PDU_index = pduindex;
cig's avatar
cig committed
1889
    tx_req->num_TLV = 1;
1890 1891
    tx_req->TLVs[0].length =  harq->tb_size;
    tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, tx_req->TLVs[0].length);
1892 1893 1894
    TX_req->SFN = frameP;
    TX_req->Number_of_PDUs++;
    TX_req->Slot = slotP;
1895

1896
    // Mark the corresponding symbols and RBs as used
1897 1898
    fill_pdcch_vrb_map(nr_mac,
                       CC_id,
1899
                       &ra->sched_pdcch,
1900 1901
                       CCEIndex,
                       aggregation_level);
1902 1903
    for (int rb = 0; rb < rbSize; rb++) {
      vrb_map[BWPStart + rb + rbStart] |= SL_to_bitmap(msg4_tda.startSymbolIndex, msg4_tda.nrOfSymbols);
1904
    }
1905

1906
    ra->state = WAIT_Msg4_ACK;
1907
    LOG_I(NR_MAC,"UE %04x Generate msg4: feedback at %4d.%2d, payload %d bytes, next state WAIT_Msg4_ACK\n", ra->rnti, pucch->frame, pucch->ul_slot, harq->tb_size);
1908 1909
  }
}
1910

1911 1912
static void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra)
{
1913
  NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, ra->rnti);
1914 1915 1916 1917
  if (!UE) {
    LOG_E(NR_MAC, "Cannot check Msg4 ACK/NACK, rnti %04x not in the table\n", ra->rnti);
    return;
  }
1918 1919
  const int current_harq_pid = ra->harq_pid;

Laurent THOMAS's avatar
Laurent THOMAS committed
1920
  NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
francescomani's avatar
francescomani committed
1921
  NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid];
1922

Laurent THOMAS's avatar
Laurent THOMAS committed
1923
  LOG_D(NR_MAC, "ue rnti 0x%04x, harq is waiting %d, round %d, frame %d %d, harq id %d\n", ra->rnti, harq->is_waiting, harq->round, frame, slot, current_harq_pid);
1924

1925 1926
  if (harq->is_waiting == 0) {
    if (harq->round == 0) {
rmagueta's avatar
rmagueta committed
1927
      if (UE->Msg4_ACKed) {
Laurent THOMAS's avatar
Laurent THOMAS committed
1928
        LOG_A(NR_MAC, "(UE RNTI 0x%04x) Received Ack of RA-Msg4. CBRA procedure succeeded!\n", ra->rnti);
1929
      } else {
1930
        LOG_I(NR_MAC, "%4d.%2d UE %04x: RA Procedure failed at Msg4!\n", frame, slot, ra->rnti);
1931
        nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs);
1932 1933
      }

1934 1935 1936 1937
      // Pause scheduling according to:
      // 3GPP TS 38.331 Section 12 Table 12.1-1: UE performance requirements for RRC procedures for UEs
      nr_mac_enable_ue_rrc_processing_timer(RC.nrmac[module_id], UE, false);

1938
      nr_clear_ra_proc(module_id, CC_id, frame, ra);
1939
      if (sched_ctrl->retrans_dl_harq.head >= 0) {
1940
        remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid);
1941
      }
1942
    } else {
Laurent THOMAS's avatar
Laurent THOMAS committed
1943
      LOG_I(NR_MAC, "(UE %04x) Received Nack of RA-Msg4. Preparing retransmission!\n", ra->rnti);
1944 1945
      ra->state = Msg4;
    }
cig's avatar
cig committed
1946
  }
1947 1948
}

1949 1950 1951 1952
void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t *ra)
{
  /* we assume that this function is mutex-protected from outside */
  NR_SCHED_ENSURE_LOCKED(&RC.nrmac[module_idP]->sched_lock);
1953
  LOG_D(NR_MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Clear Random access information rnti %x\n", module_idP, CC_id, frameP, ra->rnti);
1954
  ra->state = RA_IDLE;
cig's avatar
cig committed
1955 1956 1957
  ra->timing_offset = 0;
  ra->RRC_timer = 20;
  ra->msg3_round = 0;
1958 1959 1960
  if(ra->cfra == false) {
    ra->rnti = 0;
  }
1961 1962
}

1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987

/////////////////////////////////////
//    Random Access Response PDU   //
//         TS 38.213 ch 8.2        //
//        TS 38.321 ch 6.2.3       //
/////////////////////////////////////
//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
//| E | T |       R A P I D       |//
//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |//
//| R |           T A             |//
//|       T A         |  UL grant |//
//|            UL grant           |//
//|            UL grant           |//
//|            UL grant           |//
//|         T C - R N T I         |//
//|         T C - R N T I         |//
/////////////////////////////////////
//       UL grant  (27 bits)       //
/////////////////////////////////////
//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
//|-------------------|FHF|F_alloc|//
//|        Freq allocation        |//
//|    F_alloc    |Time allocation|//
//|      MCS      |     TPC   |CSI|//
/////////////////////////////////////
cig's avatar
cig committed
1988
// WIP
cig's avatar
cig committed
1989 1990 1991
// todo:
// - handle MAC RAR BI subheader
// - sending only 1 RAR subPDU
1992
// - UL Grant: hardcoded CSI, TPC, time alloc
cig's avatar
cig committed
1993
// - padding
1994 1995
static void nr_fill_rar(uint8_t Mod_idP, NR_RA_t *ra, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu)
{
1996
  LOG_D(NR_MAC, "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u TA command %d \n", ra->Msg2_frame, ra-> Msg2_slot, ra->preamble_index, ra->timing_offset);
1997 1998 1999
  NR_RA_HEADER_BI *rarbi = (NR_RA_HEADER_BI *) dlsch_buffer;
  NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) (dlsch_buffer + 1);
  NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 2);
Francesco Mani's avatar
Francesco Mani committed
2000
  unsigned char csi_req = 0, tpc_command;
2001

Francesco Mani's avatar
Francesco Mani committed
2002 2003
  tpc_command = 3; // this is 0 dB

2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
  /// E/T/R/R/BI subheader ///
  // E = 1, MAC PDU includes another MAC sub-PDU (RAPID)
  // T = 0, Back-off indicator subheader
  // R = 2, Reserved
  // BI = 0, 5ms
  rarbi->E = 1;
  rarbi->T = 0;
  rarbi->R = 0;
  rarbi->BI = 0;

2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032
  /// E/T/RAPID subheader ///
  // E = 0, one only RAR, first and last
  // T = 1, RAPID
  rarh->E = 0;
  rarh->T = 1;
  rarh->RAPID = ra->preamble_index;

  /// RAR MAC payload ///
  rar->R = 0;

  // TA command
  rar->TA1 = (uint8_t) (ra->timing_offset >> 5);    // 7 MSBs of timing advance
  rar->TA2 = (uint8_t) (ra->timing_offset & 0x1f);  // 5 LSBs of timing advance

  // TC-RNTI
  rar->TCRNTI_1 = (uint8_t) (ra->rnti >> 8);        // 8 MSBs of rnti
  rar->TCRNTI_2 = (uint8_t) (ra->rnti & 0xff);      // 8 LSBs of rnti

  // UL grant
2033

2034
  ra->msg3_TPC = tpc_command;
2035

2036
  if (pusch_pdu->frequency_hopping)
2037
    AssertFatal(1==0,"PUSCH with frequency hopping currently not supported");
2038

2039 2040 2041 2042 2043 2044
  int bwp_size = pusch_pdu->bwp_size;
  int prb_alloc = PRBalloc_to_locationandbandwidth0(ra->msg3_nb_rb, ra->msg3_first_rb, bwp_size);
  int valid_bits = 14;
  int f_alloc = prb_alloc & ((1 << valid_bits) - 1);

  uint32_t ul_grant = csi_req | (tpc_command << 1) | (pusch_pdu->mcs_index << 4) | (ra->Msg3_tda_id << 8) | (f_alloc << 12) | (pusch_pdu->frequency_hopping << 26);
2045

2046 2047 2048 2049
  rar->UL_GRANT_1 = (uint8_t) (ul_grant >> 24) & 0x07;
  rar->UL_GRANT_2 = (uint8_t) (ul_grant >> 16) & 0xff;
  rar->UL_GRANT_3 = (uint8_t) (ul_grant >> 8) & 0xff;
  rar->UL_GRANT_4 = (uint8_t) ul_grant & 0xff;
2050

rmagueta's avatar
rmagueta committed
2051
#ifdef DEBUG_RAR
rmagueta's avatar
rmagueta committed
2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063
  LOG_I(NR_MAC, "rarh->E = 0x%x\n", rarh->E);
  LOG_I(NR_MAC, "rarh->T = 0x%x\n", rarh->T);
  LOG_I(NR_MAC, "rarh->RAPID = 0x%x (%i)\n", rarh->RAPID, rarh->RAPID);
  LOG_I(NR_MAC, "rar->R = 0x%x\n", rar->R);
  LOG_I(NR_MAC, "rar->TA1 = 0x%x\n", rar->TA1);
  LOG_I(NR_MAC, "rar->TA2 = 0x%x\n", rar->TA2);
  LOG_I(NR_MAC, "rar->UL_GRANT_1 = 0x%x\n", rar->UL_GRANT_1);
  LOG_I(NR_MAC, "rar->UL_GRANT_2 = 0x%x\n", rar->UL_GRANT_2);
  LOG_I(NR_MAC, "rar->UL_GRANT_3 = 0x%x\n", rar->UL_GRANT_3);
  LOG_I(NR_MAC, "rar->UL_GRANT_4 = 0x%x\n", rar->UL_GRANT_4);
  LOG_I(NR_MAC, "rar->TCRNTI_1 = 0x%x\n", rar->TCRNTI_1);
  LOG_I(NR_MAC, "rar->TCRNTI_2 = 0x%x\n", rar->TCRNTI_2);
rmagueta's avatar
rmagueta committed
2064
#endif
rmagueta's avatar
rmagueta committed
2065 2066 2067

  int mcs = (unsigned char) (rar->UL_GRANT_4 >> 4);
  // time alloc
francescomani's avatar
francescomani committed
2068
  int Msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x0f);
rmagueta's avatar
rmagueta committed
2069 2070 2071 2072 2073 2074 2075 2076 2077
  // frequency alloc
  int Msg3_f_alloc = (uint16_t) ((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12));
  // frequency hopping
  int freq_hopping = (unsigned char) (rar->UL_GRANT_1 >> 2);
  // TA command
  int  ta_command = rar->TA2 + (rar->TA1 << 5);
  // TC-RNTI
  int t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);

rmagueta's avatar
rmagueta committed
2078
  LOG_D(NR_MAC, "In %s: Transmitted RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d csi_req %d t_crnti %x \n",
rmagueta's avatar
rmagueta committed
2079 2080 2081 2082 2083 2084 2085 2086 2087
        __FUNCTION__,
        Msg3_t_alloc,
        Msg3_f_alloc,
        ta_command,
        mcs,
        freq_hopping,
        tpc_command,
        csi_req,
        t_crnti);
2088
}
2089 2090 2091 2092 2093 2094 2095 2096 2097

void nr_schedule_RA(module_id_t module_idP,
                    frame_t frameP,
                    sub_frame_t slotP,
                    nfapi_nr_ul_dci_request_t *ul_dci_req,
                    nfapi_nr_dl_tti_request_t *DL_req,
                    nfapi_nr_tx_data_request_t *TX_req)
{
  gNB_MAC_INST *mac = RC.nrmac[module_idP];
2098 2099
  /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
  NR_SCHED_ENSURE_LOCKED(&mac->sched_lock);
2100 2101 2102 2103 2104 2105 2106

  start_meas(&mac->schedule_ra);
  for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
    for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
      NR_RA_t *ra = &cc->ra[i];
      LOG_D(NR_MAC, "RA[state:%d]\n", ra->state);
2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118

      // Check RA Contention Resolution timer
      if (ra->state >= WAIT_Msg3) {
        ra->contention_resolution_timer--;
        if (ra->contention_resolution_timer < 0) {
          LOG_W(NR_MAC, "(%d.%d) RA Contention Resolution timer expired for UE 0x%04x, RA procedure failed...\n", frameP, slotP, ra->rnti);
          nr_mac_release_ue(mac, ra->rnti);
          nr_clear_ra_proc(module_idP, CC_id, frameP, ra);
          continue;
        }
      }

2119 2120 2121 2122 2123 2124 2125 2126
      switch (ra->state) {
        case Msg2:
          nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req);
          break;
        case Msg3_retransmission:
          nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req);
          break;
        case Msg3_dcch_dtch:
2127
          /* fallthrough */
2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140
        case Msg4:
          nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req);
          break;
        case WAIT_Msg4_ACK:
          nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra);
          break;
        default:
          break;
      }
    }
  }
  stop_meas(&mac->schedule_ra);
}