gNB_scheduler_ulsch.c 72.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 22 23 24 25 26 27 28 29 30 31 32
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

/*! \file gNB_scheduler_ulsch.c
 * \brief gNB procedures for the ULSCH transport channel
 * \author Navid Nikaein and Raymond Knopp, Guido Casati
 * \date 2019
 * \email: guido.casati@iis.fraunhofer.de
 * \version 1.0
 * @ingroup _mac
 */


#include "LAYER2/NR_MAC_gNB/mac_proto.h"
33
#include "executables/softmodem-common.h"
34
#include "common/utils/nr/nr_common.h"
35
#include "utils.h"
36 37
#include <openair2/UTIL/OPT/opt.h>

38
#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
39

40 41
//#define SRS_IND_DEBUG

francescomani's avatar
francescomani committed
42
const int get_ul_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot) {
43 44

  /* there is a mixed slot only when in TDD */
francescomani's avatar
francescomani committed
45
  const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
46
  AssertFatal(tdd || nrmac->common_channels->frame_type == FDD, "Dynamic TDD not handled yet\n");
47

48 49
  if (tdd && tdd->nrofUplinkSymbols > 1) { // if there is uplink symbols in mixed slot
    const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + 1;
francescomani's avatar
francescomani committed
50
    if ((slot%nr_slots_period) == tdd->nrofDownlinkSlots)
51
      return 1;
52
  }
53
  return 0; // if FDD or not mixed slot in TDD, for now use default TDA (TODO handle CSI-RS slots)
54 55
}

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
//  For both UL-SCH except:
//   - UL-SCH: fixed-size MAC CE(known by LCID)
//   - UL-SCH: padding
//   - UL-SCH: MSG3 48-bits
//  |0|1|2|3|4|5|6|7|  bit-wise
//  |R|F|   LCID    |
//  |       L       |
//  |0|1|2|3|4|5|6|7|  bit-wise
//  |R|F|   LCID    |
//  |       L       |
//  |       L       |
//
//  For:
//   - UL-SCH: fixed-size MAC CE(known by LCID)
//   - UL-SCH: padding, for single/multiple 1-oct padding CE(s)
//   - UL-SCH: MSG3 48-bits
//  |0|1|2|3|4|5|6|7|  bit-wise
//  |R|R|   LCID    |
//
//  LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the corresponding MAC CE or padding as described in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID field size is 6 bits;
//  L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field per MAC subheader except for subheaders corresponding to fixed-sized MAC CEs and padding. The size of the L field is indicated by the F field;
//  F: length of L is 0:8 or 1:16 bits wide
//  R: Reserved bit, set to zero.

Laurent THOMAS's avatar
Laurent THOMAS committed
80 81
int nr_process_mac_pdu( instance_t module_idP,
			NR_UE_info_t* UE,
82 83 84 85
                        uint8_t CC_id,
                        frame_t frameP,
                        sub_frame_t slot,
                        uint8_t *pduP,
86
                        int pdu_len)
87
{
cig's avatar
cig committed
88

Laurent THOMAS's avatar
Laurent THOMAS committed
89

90
    uint8_t done = 0;
cig's avatar
cig committed
91

Laurent THOMAS's avatar
Laurent THOMAS committed
92
    NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
93

94
    if ( pduP[0] != UL_SCH_LCID_PADDING )
Laurent THOMAS's avatar
Laurent THOMAS committed
95
      trace_NRpdu(DIRECTION_UPLINK, pduP, pdu_len, WS_C_RNTI, UE->rnti, frameP, 0, 0, 0);
96 97 98 99 100

    #ifdef ENABLE_MAC_PAYLOAD_DEBUG
    LOG_I(NR_MAC, "In %s: dumping MAC PDU in %d.%d:\n", __func__, frameP, slot);
    log_dump(NR_MAC, pduP, pdu_len, LOG_DUMP_CHAR, "\n");
    #endif
cig's avatar
cig committed
101 102

    while (!done && pdu_len > 0){
103 104 105
      uint16_t mac_len=0;
      uint16_t mac_subheader_len=sizeof(NR_MAC_SUBHEADER_FIXED);
      uint8_t rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID;
cig's avatar
cig committed
106

107
        LOG_D(NR_MAC, "In %s: received UL-SCH sub-PDU with LCID 0x%x in %d.%d (remaining PDU length %d)\n", __func__, rx_lcid, frameP, slot, pdu_len);
108

ChiehChun's avatar
ChiehChun committed
109
        unsigned char *ce_ptr;
110
        int n_Lcg = 0;
ChiehChun's avatar
ChiehChun committed
111

cig's avatar
cig committed
112
        switch(rx_lcid){
113 114 115
            //  MAC CE

            /*#ifdef DEBUG_HEADER_PARSING
116
              LOG_D(NR_MAC, "[UE] LCID %d, PDU length %d\n", ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID, pdu_len);
117
            #endif*/
118 119
        case UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY:
              // 38.321 Ch6.1.3.20
120
              mac_len = 2;
121 122 123 124
              break;
        case UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION:
                // 38.321 Ch6.1.3.7
                break;
125 126 127

        case UL_SCH_LCID_S_BSR:
        case UL_SCH_LCID_S_TRUNCATED_BSR:
128 129
               //38.321 section 6.1.3.1
               //fixed length
130
               mac_len =1;
131
               /* Extract short BSR value */
132
               ce_ptr = &pduP[mac_subheader_len];
ChiehChun's avatar
ChiehChun committed
133
               NR_BSR_SHORT *bsr_s = (NR_BSR_SHORT *) ce_ptr;
134 135
               sched_ctrl->estimated_ul_buffer = 0;
               sched_ctrl->estimated_ul_buffer = NR_SHORT_BSR_TABLE[bsr_s->Buffer_size];
136
               LOG_D(NR_MAC,
137 138 139
                     "SHORT BSR at %4d.%2d, LCG ID %d, BS Index %d, BS value < %d, est buf %d\n",
                     frameP,
                     slot,
140 141 142 143
                     bsr_s->LcgID,
                     bsr_s->Buffer_size,
                     NR_SHORT_BSR_TABLE[bsr_s->Buffer_size],
                     sched_ctrl->estimated_ul_buffer);
144
               break;
145 146

        case UL_SCH_LCID_L_BSR:
147
        case UL_SCH_LCID_L_TRUNCATED_BSR:
148 149
        	//38.321 section 6.1.3.1
        	//variable length
150
                /* Several checks have been added to this function to
Melissa Elkadi's avatar
Melissa Elkadi committed
151 152 153 154
                   ensure that the casting of the pduP is possible. There seems
                   to be a partial PDU at the end of this buffer, so here
                   we gracefully ignore that by returning 0. See:
                   https://gitlab.eurecom.fr/oai/openairinterface5g/-/issues/534 */
Laurent THOMAS's avatar
Laurent THOMAS committed
155 156
	  if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
		  return 0;
157
        	/* Extract long BSR value */
158
               ce_ptr = &pduP[mac_subheader_len];
ChiehChun's avatar
ChiehChun committed
159
               NR_BSR_LONG *bsr_l = (NR_BSR_LONG *) ce_ptr;
160
               sched_ctrl->estimated_ul_buffer = 0;
161

162 163
               n_Lcg = bsr_l->LcgID7 + bsr_l->LcgID6 + bsr_l->LcgID5 + bsr_l->LcgID4 +
                       bsr_l->LcgID3 + bsr_l->LcgID2 + bsr_l->LcgID1 + bsr_l->LcgID0;
164

165
               LOG_D(NR_MAC, "LONG BSR, LCG ID(7-0) %d/%d/%d/%d/%d/%d/%d/%d\n",
166 167 168 169
                     bsr_l->LcgID7, bsr_l->LcgID6, bsr_l->LcgID5, bsr_l->LcgID4,
                     bsr_l->LcgID3, bsr_l->LcgID2, bsr_l->LcgID1, bsr_l->LcgID0);

               for (int n = 0; n < n_Lcg; n++){
170
                 LOG_D(NR_MAC, "LONG BSR, %d/%d (n/n_Lcg), BS Index %d, BS value < %d",
171 172
                       n, n_Lcg, pduP[mac_subheader_len + 1 + n],
                       NR_LONG_BSR_TABLE[pduP[mac_subheader_len + 1 + n]]);
173
                 sched_ctrl->estimated_ul_buffer +=
174
                       NR_LONG_BSR_TABLE[pduP[mac_subheader_len + 1 + n]];
175
                 LOG_D(NR_MAC,
176 177 178 179 180
                       "LONG BSR at %4d.%2d, %d/%d (n/n_Lcg), BS Index %d, BS value < %d, total %d\n",
                       frameP,
                       slot,
                       n,
                       n_Lcg,
181 182
                       pduP[mac_subheader_len + 1 + n],
                       NR_LONG_BSR_TABLE[pduP[mac_subheader_len + 1 + n]],
183
                       sched_ctrl->estimated_ul_buffer);
184 185
               }

186
               break;
187 188

        case UL_SCH_LCID_C_RNTI:
189 190 191

          for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
            NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i];
Laurent THOMAS's avatar
Laurent THOMAS committed
192
            if (ra->state >= WAIT_Msg3 && ra->rnti == UE->rnti) {
193
              ra->crnti = ((pduP[1]&0xFF)<<8)|(pduP[2]&0xFF);
194 195
              ra->msg3_dcch_dtch = true;
              LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x\n", ra->crnti);
196 197 198 199
              break;
            }
          }

200 201
        	//38.321 section 6.1.3.2
        	//fixed length
202
        	mac_len = 2;
203 204 205 206 207 208
        	/* Extract CRNTI value */
        	break;

        case UL_SCH_LCID_SINGLE_ENTRY_PHR:
        	//38.321 section 6.1.3.8
        	//fixed length
209
        	mac_len = 2;
210
        	/* Extract SINGLE ENTRY PHR elements for PHR calculation */
211
        	ce_ptr = &pduP[mac_subheader_len];
212 213 214 215 216 217 218 219 220 221 222
        	NR_SINGLE_ENTRY_PHR_MAC_CE *phr = (NR_SINGLE_ENTRY_PHR_MAC_CE *) ce_ptr;
        	/* Save the phr info */
        	const int PH = phr->PH;
        	const int PCMAX = phr->PCMAX;
        	/* 38.133 Table10.1.17.1-1 */
        	if (PH < 55)
        	  sched_ctrl->ph = PH - 32;
        	else
        	  sched_ctrl->ph = PH - 32 + (PH - 54);
        	/* 38.133 Table10.1.18.1-1 */
        	sched_ctrl->pcmax = PCMAX - 29;
223
        	LOG_D(NR_MAC, "SINGLE ENTRY PHR R1 %d PH %d (%d dB) R2 %d PCMAX %d (%d dBm)\n",
224
                      phr->R1, PH, sched_ctrl->ph, phr->R2, PCMAX, sched_ctrl->pcmax);
225 226 227 228 229
        	break;

        case UL_SCH_LCID_MULTI_ENTRY_PHR_1_OCT:
        	//38.321 section 6.1.3.9
        	//  varialbe length
Laurent THOMAS's avatar
Laurent THOMAS committed
230 231
	  if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
	    return 0;
232 233 234 235 236 237
        	/* Extract MULTI ENTRY PHR elements from single octet bitmap for PHR calculation */
        	break;

        case UL_SCH_LCID_MULTI_ENTRY_PHR_4_OCT:
        	//38.321 section 6.1.3.9
        	//  varialbe length
Laurent THOMAS's avatar
Laurent THOMAS committed
238 239
	  if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
	    return 0;
240 241 242 243 244 245 246 247
        	/* Extract MULTI ENTRY PHR elements from four octets bitmap for PHR calculation */
        	break;

        case UL_SCH_LCID_PADDING:
        	done = 1;
        	//  end of MAC PDU, can ignore the rest.
        	break;

248
        case UL_SCH_LCID_SRB1:
249
        case UL_SCH_LCID_SRB2:
Laurent THOMAS's avatar
Laurent THOMAS committed
250 251
	  if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
	    return 0;
252

Laurent THOMAS's avatar
Laurent THOMAS committed
253 254
          rnti_t crnti = UE->rnti;
	  NR_UE_info_t* UE_idx = UE;
255 256
          for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
            NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i];
Laurent THOMAS's avatar
Laurent THOMAS committed
257
            if (ra->state >= WAIT_Msg3 && ra->rnti == UE->rnti) {
258 259
              uint8_t *next_subpduP = pduP + mac_subheader_len + mac_len;
              if ((pduP[mac_subheader_len+mac_len] & 0x3F) == UL_SCH_LCID_C_RNTI) {
260
                crnti = ((next_subpduP[1]&0xFF)<<8)|(next_subpduP[2]&0xFF);
Laurent THOMAS's avatar
Laurent THOMAS committed
261 262
		LOG_W(NR_MAC, " UL_SCH_LCID_SRB for rnti %04x\n", crnti);
                UE_idx = find_nr_UE(&RC.nrmac[module_idP]->UE_info, crnti);
263 264 265 266 267
                break;
              }
            }
          }

Laurent THOMAS's avatar
Laurent THOMAS committed
268 269
          if (UE_idx->CellGroup) {
            LOG_D(NR_MAC, "Frame %d : ULSCH -> UL-DCCH %d (gNB %ld, %d bytes), rnti: 0x%04x \n", frameP, rx_lcid, module_idP, mac_len, crnti);
Eurecom's avatar
Eurecom committed
270
            mac_rlc_data_ind(module_idP,
271
                             crnti,
Eurecom's avatar
Eurecom committed
272 273 274 275 276
                             module_idP,
                             frameP,
                             ENB_FLAG_YES,
                             MBMS_FLAG_NO,
                             rx_lcid,
277
                             (char *) (pduP + mac_subheader_len),
278
                             mac_len,
Eurecom's avatar
Eurecom committed
279 280 281
                             1,
                             NULL);
          } else {
Laurent THOMAS's avatar
Laurent THOMAS committed
282
            AssertFatal(1==0,"[UE %04x] Frame/Slot %d.%d : Received LCID %d which is not configured, dropping packet\n",UE->rnti,frameP,slot,rx_lcid);
Eurecom's avatar
Eurecom committed
283
          }
284
          break;
285 286 287
        case UL_SCH_LCID_SRB3:
              // todo
              break;
288

289
        case UL_SCH_LCID_CCCH:
290
        case UL_SCH_LCID_CCCH1:
291
          // fixed length
292
          mac_subheader_len = 1;
293 294 295

          if ( rx_lcid == UL_SCH_LCID_CCCH1 ) {
            // RRCResumeRequest1 message includes the full I-RNTI and has a size of 8 bytes
296
            mac_len = 8;
297

rmagueta's avatar
rmagueta committed
298
            // Check if it is a valid CCCH1 message, we get all 00's messages very often
299
            int i = 0;
300
            for(i=0; i<(mac_subheader_len+mac_len); i++) {
301
              if(pduP[i] != 0) {
302 303 304
                break;
              }
            }
305
            if (i == (mac_subheader_len+mac_len)) {
rmagueta's avatar
rmagueta committed
306
              LOG_D(NR_MAC, "%s() Invalid CCCH1 message!, pdu_len: %d\n", __func__, pdu_len);
307 308
              done = 1;
              break;
309 310 311
            }
          } else {
            // fixed length of 6 bytes
312
            mac_len = 6;
313 314
          }

315 316 317 318 319 320
          send_initial_ul_rrc_message(module_idP,
                                      CC_id,
                                      UE,
                                      CCCH,
                                      pduP + mac_subheader_len,
                                      mac_len);
321
          break;
322

323
        case UL_SCH_LCID_DTCH ... (UL_SCH_LCID_DTCH + 28):
324
          //  check if LCID is valid at current time.
325 326 327
          if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) {
            return 0;
          }
328

Laurent THOMAS's avatar
Laurent THOMAS committed
329

330 331 332 333 334 335 336 337 338
            LOG_D(NR_MAC, "[UE %04x] %d.%d : ULSCH -> UL-%s %d (gNB %ld, %d bytes)\n",
                  UE->rnti,
                  frameP,
                  slot,
                  rx_lcid<4?"DCCH":"DTCH",
                  rx_lcid,
                  module_idP,
                  mac_len);
            UE->mac_stats.ul.lc_bytes[rx_lcid] += mac_len;
339

340
            mac_rlc_data_ind(module_idP,
341
                             UE->rnti,
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
                             module_idP,
                             frameP,
                             ENB_FLAG_YES,
                             MBMS_FLAG_NO,
                             rx_lcid,
                             (char *)(pduP + mac_subheader_len),
                             mac_len,
                             1,
                             NULL);

            /* Updated estimated buffer when receiving data */
            if (sched_ctrl->estimated_ul_buffer >= mac_len) {
              sched_ctrl->estimated_ul_buffer -= mac_len;
            } else {
              sched_ctrl->estimated_ul_buffer = 0;
            }

            break;
360 361

        default:
362
          LOG_E(NR_MAC, "Received unknown MAC header (LCID = 0x%02x)\n", rx_lcid);
Eurecom's avatar
Eurecom committed
363
          return -1;
364
          break;
cig's avatar
cig committed
365
        }
366 367 368 369 370

        #ifdef ENABLE_MAC_PAYLOAD_DEBUG
        if (rx_lcid < 45 || rx_lcid == 52 || rx_lcid == 63) {
          LOG_I(NR_MAC, "In %s: dumping UL MAC SDU sub-header with length %d (LCID = 0x%02x):\n", __func__, mac_subheader_len, rx_lcid);
          log_dump(NR_MAC, pduP, mac_subheader_len, LOG_DUMP_CHAR, "\n");
371 372
          LOG_I(NR_MAC, "In %s: dumping UL MAC SDU with length %d (LCID = 0x%02x):\n", __func__, mac_len, rx_lcid);
          log_dump(NR_MAC, pduP + mac_subheader_len, mac_len, LOG_DUMP_CHAR, "\n");
373
        } else {
374 375
          LOG_I(NR_MAC, "In %s: dumping UL MAC CE with length %d (LCID = 0x%02x):\n", __func__, mac_len, rx_lcid);
          log_dump(NR_MAC, pduP + mac_subheader_len + mac_len, mac_len, LOG_DUMP_CHAR, "\n");
376 377 378
        }
        #endif

379 380
        pduP += ( mac_subheader_len + mac_len );
        pdu_len -= ( mac_subheader_len + mac_len );
cig's avatar
cig committed
381

382
        if (pdu_len < 0) {
383
          LOG_E(NR_MAC, "In %s: residual UL MAC PDU in %d.%d with length < 0!, pdu_len %d \n", __func__, frameP, slot, pdu_len);
384
          LOG_E(NR_MAC, "MAC PDU ");
385
          for (int i = 0; i < 20; i++) // Only printf 1st - 20nd bytes
386
            printf("%02x ", pduP[i]);
387
          printf("\n");
Eurecom's avatar
Eurecom committed
388
          return 0;
389
        }
390
    }
Eurecom's avatar
Eurecom committed
391
  return 0;
392
}
393

394
void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid)
395
{
Laurent THOMAS's avatar
Laurent THOMAS committed
396
  NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
397 398 399 400
  NR_UE_ul_harq_t *harq = &sched_ctrl->ul_harq_processes[harq_pid];

  harq->ndi ^= 1;
  harq->round = 0;
Laurent THOMAS's avatar
Laurent THOMAS committed
401
  UE->mac_stats.ul.errors++;
402 403 404 405 406 407 408 409 410
  add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid);

  /* the transmission failed: the UE won't send the data we expected initially,
   * so retrieve to correctly schedule after next BSR */
  sched_ctrl->sched_ul_bytes -= harq->sched_pusch.tb_size;
  if (sched_ctrl->sched_ul_bytes < 0)
    sched_ctrl->sched_ul_bytes = 0;
}

411 412
void handle_nr_ul_harq(const int CC_idP,
                       module_id_t mod_id,
413 414 415 416
                       frame_t frame,
                       sub_frame_t slot,
                       const nfapi_nr_crc_t *crc_pdu)
{
Laurent THOMAS's avatar
Laurent THOMAS committed
417 418 419
  NR_UE_info_t* UE = find_nr_UE(&RC.nrmac[mod_id]->UE_info, crc_pdu->rnti);
  if (!UE) {
    LOG_W(NR_MAC, "handle harq for rnti %04x, in RA process\n", crc_pdu->rnti);
420
    for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
Laurent THOMAS's avatar
Laurent THOMAS committed
421
      NR_RA_t *ra = &RC.nrmac[mod_id]->common_channels[CC_idP].ra[i];
422 423 424 425
      if (ra->state >= WAIT_Msg3 &&
          ra->rnti == crc_pdu->rnti)
        return;
    }
426
    LOG_E(NR_MAC, "%s(): unknown RNTI 0x%04x in PUSCH\n", __func__, crc_pdu->rnti);
427 428
    return;
  }
Laurent THOMAS's avatar
Laurent THOMAS committed
429
  NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
430
  int8_t harq_pid = sched_ctrl->feedback_ul_harq.head;
431
  LOG_D(NR_MAC, "Comparing crc_pdu->harq_id vs feedback harq_pid = %d %d\n",crc_pdu->harq_id, harq_pid);
432
  while (crc_pdu->harq_id != harq_pid || harq_pid < 0) {
433
    LOG_W(NR_MAC,
434
          "Unexpected ULSCH HARQ PID %d (have %d) for RNTI 0x%04x (ignore this warning for RA)\n",
435 436
          crc_pdu->harq_id,
          harq_pid,
437
          crc_pdu->rnti);
438 439 440 441
    if (harq_pid < 0)
      return;

    remove_front_nr_list(&sched_ctrl->feedback_ul_harq);
442
    sched_ctrl->ul_harq_processes[harq_pid].is_waiting = false;
Laurent THOMAS's avatar
Laurent THOMAS committed
443

444
    if(sched_ctrl->ul_harq_processes[harq_pid].round >= RC.nrmac[mod_id]->ul_bler.harq_round_max - 1) {
Laurent THOMAS's avatar
Laurent THOMAS committed
445
      abort_nr_ul_harq(UE, harq_pid);
446 447 448 449
    } else {
      sched_ctrl->ul_harq_processes[harq_pid].round++;
      add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid);
    }
450
    harq_pid = sched_ctrl->feedback_ul_harq.head;
451 452 453 454 455 456 457 458 459
  }
  remove_front_nr_list(&sched_ctrl->feedback_ul_harq);
  NR_UE_ul_harq_t *harq = &sched_ctrl->ul_harq_processes[harq_pid];
  DevAssert(harq->is_waiting);
  harq->feedback_slot = -1;
  harq->is_waiting = false;
  if (!crc_pdu->tb_crc_status) {
    harq->ndi ^= 1;
    harq->round = 0;
460
    LOG_D(NR_MAC,
461 462 463 464
          "Ulharq id %d crc passed for RNTI %04x\n",
          harq_pid,
          crc_pdu->rnti);
    add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid);
465
  } else if (harq->round >= RC.nrmac[mod_id]->ul_bler.harq_round_max  - 1) {
Laurent THOMAS's avatar
Laurent THOMAS committed
466
    abort_nr_ul_harq(UE, harq_pid);
467
    LOG_D(NR_MAC,
468 469 470 471 472
          "RNTI %04x: Ulharq id %d crc failed in all rounds\n",
          crc_pdu->rnti,
          harq_pid);
  } else {
    harq->round++;
473
    LOG_D(NR_MAC,
474 475 476 477 478
          "Ulharq id %d crc failed for RNTI %04x\n",
          harq_pid,
          crc_pdu->rnti);
    add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid);
  }
479
}
480

481 482 483
/*
* When data are received on PHY and transmitted to MAC
*/
484 485 486
void nr_rx_sdu(const module_id_t gnb_mod_idP,
               const int CC_idP,
               const frame_t frameP,
487
               const sub_frame_t slotP,
488 489 490 491
               const rnti_t rntiP,
               uint8_t *sduP,
               const uint16_t sdu_lenP,
               const uint16_t timing_advance,
492 493
               const uint8_t ul_cqi,
               const uint16_t rssi){
494

Robert Schmidt's avatar
Robert Schmidt committed
495 496 497
  gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP];

  const int current_rnti = rntiP;
Laurent THOMAS's avatar
Laurent THOMAS committed
498
  LOG_D(NR_MAC, "rx_sdu for rnti %04x\n", current_rnti);
Robert Schmidt's avatar
Robert Schmidt committed
499
  const int target_snrx10 = gNB_mac->pusch_target_snrx10;
500
  const int pusch_failure_thres = gNB_mac->pusch_failure_thres;
Laurent THOMAS's avatar
Laurent THOMAS committed
501 502 503 504
  
  NR_UE_info_t* UE = find_nr_UE(&gNB_mac->UE_info, current_rnti);
  if (UE) {
    NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl;
Robert Schmidt's avatar
Robert Schmidt committed
505 506 507 508 509 510
    const int8_t harq_pid = UE_scheduling_control->feedback_ul_harq.head;

    if (sduP)
      T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
        T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(harq_pid),
        T_BUFFER(sduP, sdu_lenP));
511

Laurent THOMAS's avatar
Laurent THOMAS committed
512 513
    UE->mac_stats.ul.total_bytes += sdu_lenP;
    LOG_D(NR_MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %04x) ul_cqi %d TA %d sduP %p, rssi %d\n",
514 515 516 517
          gnb_mod_idP,
          harq_pid,
          CC_idP,
          frameP,
518
          slotP,
519
          current_rnti,
520
          ul_cqi,
521
          timing_advance,
522 523
          sduP,
          rssi);
524

525
    // if not missed detection (10dB threshold for now)
526
    if (rssi>0) {
527
      UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10,ul_cqi,30);
528 529
      if (timing_advance != 0xffff)
        UE_scheduling_control->ta_update = timing_advance;
530 531
      UE_scheduling_control->raw_rssi = rssi;
      UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640;
Laurent THOMAS's avatar
Laurent THOMAS committed
532 533

      LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n",UE->rnti,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update);
534 535
    }
    else{
Laurent THOMAS's avatar
Laurent THOMAS committed
536
      LOG_D(NR_MAC,"[UE %04x] Detected DTX : increasing UE TX power\n",UE->rnti);
537
      UE_scheduling_control->tpc0 = 1;
538 539
    }

540
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
Laurent's avatar
Laurent committed
541

542
    LOG_I(NR_MAC, "Printing received UL MAC payload at gNB side: %d \n");
543
    for (int i = 0; i < sdu_lenP ; i++) {
544 545 546
	  //harq_process_ul_ue->a[i] = (unsigned char) rand();
	  //printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]);
	  printf("%02x ",(unsigned char)sduP[i]);
547 548
    }
    printf("\n");
Laurent's avatar
Laurent committed
549

550 551 552
#endif

    if (sduP != NULL){
rmagueta's avatar
rmagueta committed
553
      LOG_D(NR_MAC, "Received PDU at MAC gNB \n");
554

Laurent THOMAS's avatar
Laurent THOMAS committed
555
      UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt = 0;
556 557
      const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size;
      UE_scheduling_control->sched_ul_bytes -= tb_size;
558 559 560
      if (UE_scheduling_control->sched_ul_bytes < 0)
        UE_scheduling_control->sched_ul_bytes = 0;

Laurent THOMAS's avatar
Laurent THOMAS committed
561
      nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP);
562 563
    }
    else {
564 565 566
      NR_UE_ul_harq_t *cur_harq = &UE_scheduling_control->ul_harq_processes[harq_pid];
      /* reduce sched_ul_bytes when cur_harq->round == 3 */
      if (cur_harq->round == 3){
567 568
        const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size;
        UE_scheduling_control->sched_ul_bytes -= tb_size;
569 570 571
        if (UE_scheduling_control->sched_ul_bytes < 0)
          UE_scheduling_control->sched_ul_bytes = 0;
      }
572
      if (ul_cqi <= 128) {
Laurent THOMAS's avatar
Laurent THOMAS committed
573 574
        UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt++;
        UE->mac_stats.ulsch_DTX++;
575
      }
Laurent THOMAS's avatar
Laurent THOMAS committed
576 577 578 579 580 581

      if (!get_softmodem_params()->phy_test && UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt >= pusch_failure_thres) {
         LOG_W(NR_MAC,"Detected UL Failure on PUSCH after %d PUSCH DTX, stopping scheduling\n",
               UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt);
         UE->UE_sched_ctrl.ul_failure = 1;

rmagueta's avatar
rmagueta committed
582
         nr_mac_gNB_rrc_ul_failure(gnb_mod_idP,CC_idP,frameP,slotP,rntiP);
583
      }
584
    }
585 586 587 588 589 590 591 592 593 594 595 596 597
  } else if(sduP) {

    bool no_sig = true;
    for (int k = 0; k < sdu_lenP; k++) {
      if(sduP[k]!=0) {
        no_sig = false;
        break;
      }
    }

    if(no_sig) {
      LOG_W(NR_MAC, "No signal\n");
    }
598

Robert Schmidt's avatar
Robert Schmidt committed
599 600 601
    T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
      T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */,
      T_BUFFER(sduP, sdu_lenP));
Laurent THOMAS's avatar
Laurent THOMAS committed
602
    
603 604 605 606 607 608 609
    /* we don't know this UE (yet). Check whether there is a ongoing RA (Msg 3)
     * and check the corresponding UE's RNTI match, in which case we activate
     * it. */
    for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
      NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i];
      if (ra->state != WAIT_Msg3)
        continue;
Laurent THOMAS's avatar
Laurent THOMAS committed
610
      
611
      if(no_sig) {
612
        LOG_D(NR_MAC, "Random Access %i failed at state %i (no signal)\n", i, ra->state);
613
        nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti);
614
        nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
615 616 617 618
      } else {

        // random access pusch with TC-RNTI
        if (ra->rnti != current_rnti) {
619
          LOG_D(NR_MAC,
rmagueta's avatar
rmagueta committed
620
                "expected TC_RNTI %04x to match current RNTI %04x\n",
621 622
                ra->rnti,
                current_rnti);
rmagueta's avatar
rmagueta committed
623 624

          if( (frameP==ra->Msg3_frame) && (slotP==ra->Msg3_slot) ) {
625
            LOG_D(NR_MAC, "Random Access %i failed at state %i (TC_RNTI %04x RNTI %04x)\n", i, ra->state,ra->rnti,current_rnti);
rmagueta's avatar
rmagueta committed
626 627 628 629
            nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti);
            nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
          }

630 631
          continue;
        }
rmagueta's avatar
rmagueta committed
632

633

Laurent THOMAS's avatar
Laurent THOMAS committed
634 635 636 637
	NR_UE_info_t* UE = add_new_nr_ue(gNB_mac, ra->rnti, ra->CellGroup);
        if (!UE) {
          LOG_W(NR_MAC, "Random Access %i discarded at state %i (TC_RNTI %04x RNTI %04x): max number of users achieved!\n", i, ra->state,ra->rnti,current_rnti);

638 639 640 641 642
          nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti);
          nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
          return;
        }

Laurent THOMAS's avatar
Laurent THOMAS committed
643
        UE->UE_beam_index = ra->beam_id;
rmagueta's avatar
rmagueta committed
644 645

        // re-initialize ta update variables after RA procedure completion
Laurent THOMAS's avatar
Laurent THOMAS committed
646
        UE->UE_sched_ctrl.ta_frame = frameP;
rmagueta's avatar
rmagueta committed
647

rmagueta's avatar
rmagueta committed
648
        LOG_D(NR_MAC,
649
              "reset RA state information for RA-RNTI 0x%04x/index %d\n",
650
              ra->rnti,
651
              i);
652

653
        LOG_I(NR_MAC,
654
              "[gNB %d][RAPROC] PUSCH with TC_RNTI 0x%04x received correctly, "
Laurent THOMAS's avatar
Laurent THOMAS committed
655
              "adding UE MAC Context RNTI 0x%04x\n",
656 657 658
              gnb_mod_idP,
              current_rnti,
              ra->rnti);
659

Laurent THOMAS's avatar
Laurent THOMAS committed
660
      NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl;
661 662 663 664 665 666

      UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10,ul_cqi,30);
      if (timing_advance != 0xffff)
        UE_scheduling_control->ta_update = timing_advance;
      UE_scheduling_control->raw_rssi = rssi;
      UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640;
Laurent THOMAS's avatar
Laurent THOMAS committed
667
      LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n",UE->rnti,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update);
668
        if(ra->cfra) {
669

Laurent THOMAS's avatar
Laurent THOMAS committed
670
          LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", ra->rnti);
671
          nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti);
672
          nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
673 674
          process_CellGroup(ra->CellGroup, UE_scheduling_control);

675
        } else {
676

677
          LOG_A(NR_MAC,"[RAPROC] RA-Msg3 received (sdu_lenP %d)\n",sdu_lenP);
rmagueta's avatar
rmagueta committed
678
          LOG_D(NR_MAC,"[RAPROC] Received Msg3:\n");
679
          for (int k = 0; k < sdu_lenP; k++) {
rmagueta's avatar
rmagueta committed
680
            LOG_D(NR_MAC,"(%i): 0x%x\n",k,sduP[k]);
681
          }
682

683 684 685 686
          // UE Contention Resolution Identity
          // Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4
          // First byte corresponds to R/LCID MAC sub-header
          memcpy(ra->cont_res_id, &sduP[1], sizeof(uint8_t) * 6);
687

Laurent THOMAS's avatar
Laurent THOMAS committed
688
          if (nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP) == 0) {
689 690 691
            ra->state = Msg4;
            ra->Msg4_frame = (frameP + 2) % 1024;
            ra->Msg4_slot = 1;
692 693
            
            if (ra->msg3_dcch_dtch) {
694
              // Check if the UE identified by C-RNTI still exists at the gNB
Laurent THOMAS's avatar
Laurent THOMAS committed
695 696
              NR_UE_info_t * UE_C = find_nr_UE(&gNB_mac->UE_info, ra->crnti);
              if (!UE_C) {
697 698
                // The UE identified by C-RNTI no longer exists at the gNB
                // Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better solution may be implemented
Laurent THOMAS's avatar
Laurent THOMAS committed
699
                mac_remove_nr_ue(gNB_mac, ra->rnti);
700 701 702
                nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
                return;
              } else {
703
                // The UE identified by C-RNTI still exists at the gNB
704
                // Reset uplink failure flags/counters/timers at RRC
705
                nr_mac_gNB_rrc_ul_failure_reset(gnb_mod_idP, frameP, slotP, ra->crnti);
706 707 708 709

                // Reset HARQ processes
                reset_dl_harq_list(&UE_C->UE_sched_ctrl);
                reset_ul_harq_list(&UE_C->UE_sched_ctrl);
710 711
              }
            }
712 713
            LOG_I(NR_MAC, "Scheduling RA-Msg4 for TC_RNTI 0x%04x (state %d, frame %d, slot %d)\n",
                  (ra->msg3_dcch_dtch?ra->crnti:ra->rnti), ra->state, ra->Msg4_frame, ra->Msg4_slot);
Eurecom's avatar
Eurecom committed
714 715 716 717 718
          }
          else {
             nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti);
             nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
          }
719
        }
720
        return;
721
      }
722 723 724 725 726 727
    }
  } else {
    for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
      NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i];
      if (ra->state != WAIT_Msg3)
        continue;
728

729 730 731
      if( (frameP!=ra->Msg3_frame) || (slotP!=ra->Msg3_slot))
        continue;

732 733
      // for CFRA (NSA) do not schedule retransmission of msg3
      if (ra->cfra) {
734
        LOG_D(NR_MAC, "Random Access %i failed at state %i (NSA msg3 reception failed)\n", i, ra->state);
735 736 737 738 739
        nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti);
        nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
        return;
      }

740 741
      if (ra->msg3_round >= gNB_mac->ul_bler.harq_round_max - 1) {
        LOG_W(NR_MAC, "Random Access %i failed at state %i (Reached msg3 max harq rounds)\n", i, ra->state);
742 743 744 745 746
        nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti);
        nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
        return;
      }

747
      LOG_D(NR_MAC, "Random Access %i Msg3 CRC did not pass)\n", i);
Laurent THOMAS's avatar
Laurent THOMAS committed
748

749
      ra->msg3_round++;
750
      ra->state = Msg3_retransmission;
751
    }
752
  }
753 754
}

755 756 757 758 759 760 761 762 763
void handle_nr_srs_measurements(const module_id_t module_id,
                                const frame_t frame,
                                const sub_frame_t slot,
                                const rnti_t rnti,
                                const uint16_t timing_advance,
                                const uint8_t num_symbols,
                                const uint8_t wide_band_snr,
                                const uint8_t num_reported_symbols,
                                nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list) {
764

765
  LOG_D(NR_MAC, "(%d.%d) Received SRS indication for rnti: 0x%04x\n", frame, slot, rnti);
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780

#ifdef SRS_IND_DEBUG
  LOG_I(NR_MAC, "frame = %i\n", frame);
  LOG_I(NR_MAC, "slot = %i\n", slot);
  LOG_I(NR_MAC, "rnti = 0x%04x\n", rnti);
  LOG_I(NR_MAC, "timing_advance = %i\n", timing_advance);
  LOG_I(NR_MAC, "num_symbols = %i\n", num_symbols);
  LOG_I(NR_MAC, "wide_band_snr = %i (%i dB)\n", wide_band_snr, (wide_band_snr>>1)-64);
  LOG_I(NR_MAC, "num_reported_symbols = %i\n", num_reported_symbols);
  LOG_I(NR_MAC, "reported_symbol_list[0].num_rbs = %i\n", reported_symbol_list[0].num_rbs);
  for(int rb = 0; rb < reported_symbol_list[0].num_rbs; rb++) {
    LOG_I(NR_MAC, "reported_symbol_list[0].rb_list[%3i].rb_snr = %i (%i dB)\n",
          rb, reported_symbol_list[0].rb_list[rb].rb_snr, (reported_symbol_list[0].rb_list[rb].rb_snr>>1)-64);
  }
#endif
781

782
  NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, rnti);
Roberto Louro Magueta's avatar
Roberto Louro Magueta committed
783
  if (!UE) {
784 785 786 787 788
    LOG_W(NR_MAC, "Could not find UE for RNTI 0x%04x\n", rnti);
    return;
  }

  gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
Roberto Louro Magueta's avatar
Roberto Louro Magueta committed
789
  NR_mac_stats_t *stats = &UE->mac_stats;
790 791
  stats->srs_wide_band_snr = (wide_band_snr>>1)-64;

792
  const int ul_prbblack_SNR_threshold = nr_mac->ul_prbblack_SNR_threshold;
793
  uint16_t *ulprbbl = nr_mac->ulprbbl;
794 795 796 797 798 799 800 801 802

  memset(ulprbbl, 0, reported_symbol_list[0].num_rbs*sizeof(uint16_t));
  for (int rb = 0; rb < reported_symbol_list[0].num_rbs; rb++) {
    int snr = (reported_symbol_list[0].rb_list[rb].rb_snr>>1)-64;
    if (snr < ul_prbblack_SNR_threshold) {
      ulprbbl[rb] = 0x3FFF; // all symbols taken
    }
    LOG_D(NR_MAC, "ulprbbl[%3i] = 0x%x\n", rb, ulprbbl[rb]);
  }
803 804
}

805
long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList,
806 807 808
            int time_domain_assignment,
            int mu) {

809
  NR_PUSCH_TimeDomainResourceAllocation_t *tda = tdaList->list.array[time_domain_assignment];
810

811 812
  if (tda->k2)
    return *tda->k2;
813 814 815 816 817 818 819 820
  else if (mu < 2)
    return 1;
  else if (mu == 2)
    return 2;
  else
    return 3;
}

Laurent THOMAS's avatar
Laurent THOMAS committed
821 822
static bool nr_UE_is_to_be_scheduled(const NR_ServingCellConfigCommon_t *scc,
			      int CC_id,  NR_UE_info_t* UE, frame_t frame, sub_frame_t slot, uint32_t ulsch_max_frame_inactivity)
823
{
824
  const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
825 826
  const int now = frame * n + slot;

Laurent THOMAS's avatar
Laurent THOMAS committed
827 828
  const NR_UE_sched_ctrl_t *sched_ctrl =&UE->UE_sched_ctrl;

829 830 831
  const NR_TDD_UL_DL_Pattern_t *tdd =
      scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
  int num_slots_per_period;
Laurent THOMAS's avatar
Laurent THOMAS committed
832
  int last_ul_slot;
833
  int tdd_period_len[8] = {500,625,1000,1250,2000,2500,5000,10000};
834
  if (tdd) { // Force the default transmission in a full slot as early as possible in the UL portion of TDD period (last_ul_slot)
835
    num_slots_per_period = n*tdd_period_len[tdd->dl_UL_TransmissionPeriodicity]/10000;
836
    last_ul_slot=1+tdd->nrofDownlinkSlots;
837
  } else {
838
    num_slots_per_period = n;
839
    last_ul_slot = sched_ctrl->last_ul_slot;
840
  }
841

Laurent THOMAS's avatar
Laurent THOMAS committed
842
  const int last_ul_sched = sched_ctrl->last_ul_frame * n + last_ul_slot;
843 844 845 846 847 848
  const int diff = (now - last_ul_sched + 1024 * n) % (1024 * n);
  /* UE is to be scheduled if
   * (1) we think the UE has more bytes awaiting than what we scheduled
   * (2) there is a scheduling request
   * (3) or we did not schedule it in more than 10 frames */
  const bool has_data = sched_ctrl->estimated_ul_buffer > sched_ctrl->sched_ul_bytes;
Laurent THOMAS's avatar
Laurent THOMAS committed
849
  const bool high_inactivity = diff >= (ulsch_max_frame_inactivity > 0 ? ulsch_max_frame_inactivity * n : num_slots_per_period);
850
  LOG_D(NR_MAC,
851 852 853 854 855 856 857 858 859
        "%4d.%2d UL inactivity %d slots has_data %d SR %d\n",
        frame,
        slot,
        diff,
        has_data,
        sched_ctrl->SR);
  return has_data || sched_ctrl->SR || high_inactivity;
}

Laurent THOMAS's avatar
Laurent THOMAS committed
860 861 862 863 864 865 866 867 868 869
static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac,
				       frame_t frame,
				       sub_frame_t slot,
				       uint16_t *rballoc_mask,
				       int *n_rb_sched,
				       NR_UE_info_t* UE,
				       int harq_pid,
				       const NR_SIB1_t *sib1,
				       const NR_ServingCellConfigCommon_t *scc,
				       const int tda)
870 871
{
  const int CC_id = 0;
Laurent THOMAS's avatar
Laurent THOMAS committed
872
  NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
873
  NR_sched_pusch_t *retInfo = &sched_ctrl->ul_harq_processes[harq_pid].sched_pusch;
874

875
  int rbStart = 0; // wrt BWP start
876
  const uint16_t bwpSize = UE->current_UL_BWP.BWPSize;
877
  const uint8_t nrOfLayers = 1;
878
  LOG_D(NR_MAC,"retInfo->time_domain_allocation = %d, tda = %d\n", retInfo->time_domain_allocation, tda);
francescomani's avatar
francescomani committed
879
  LOG_D(NR_MAC,"tbs %d\n",retInfo->tb_size);
880 881 882 883
  if (tda == retInfo->time_domain_allocation) {
    /* check whether we need to switch the TDA allocation since tha last
     * (re-)transmission */
    NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static;
Eurecom's avatar
Eurecom committed
884

885
    if (ps->time_domain_allocation != tda
francescomani's avatar
francescomani committed
886
        || ps->nrOfLayers != nrOfLayers) {
887
      nr_set_pusch_semi_static(&UE->current_UL_BWP,
888 889
                               scc,
                               tda,
890
                               nrOfLayers,
891
                               ps);
892
    }
893 894

    /* Check the resource is enough for retransmission */
895 896
    const uint16_t slbitmap = SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols);
    while (rbStart < bwpSize && (rballoc_mask[rbStart] & slbitmap) != slbitmap)
897 898
      rbStart++;
    if (rbStart + retInfo->rbSize > bwpSize) {
Laurent THOMAS's avatar
Laurent THOMAS committed
899
      LOG_W(NR_MAC, "cannot allocate retransmission of RNTI %04x: no resources (rbStart %d, retInfo->rbSize %d, bwpSize %d\n", UE->rnti, rbStart, retInfo->rbSize, bwpSize);
900 901
      return false;
    }
902
    LOG_D(NR_MAC, "%s(): retransmission keeping TDA %d and TBS %d\n", __func__, tda, retInfo->tb_size);
903
  } else {
904
    NR_pusch_semi_static_t temp_ps;
905
    nr_set_pusch_semi_static(&UE->current_UL_BWP,
906 907
                             scc,
                             tda,
908
                             nrOfLayers,
909
                             &temp_ps);
910 911
    /* the retransmission will use a different time domain allocation, check
     * that we have enough resources */
912 913
    const uint16_t slbitmap = SL_to_bitmap(temp_ps.startSymbolIndex, temp_ps.nrOfSymbols);
    while (rbStart < bwpSize && (rballoc_mask[rbStart] & slbitmap) != slbitmap)
914 915
      rbStart++;
    int rbSize = 0;
916
    while (rbStart + rbSize < bwpSize && (rballoc_mask[rbStart + rbSize] & slbitmap) == slbitmap)
917 918 919 920 921
      rbSize++;
    uint32_t new_tbs;
    uint16_t new_rbSize;
    bool success = nr_find_nb_rb(retInfo->Qm,
                                 retInfo->R,
922
                                 1, // layers
923 924 925
                                 temp_ps.nrOfSymbols,
                                 temp_ps.N_PRB_DMRS * temp_ps.num_dmrs_symb,
                                 retInfo->tb_size,
926
                                 1, /* minimum of 1RB: need to find exact TBS, don't preclude any number */
927 928 929 930
                                 rbSize,
                                 &new_tbs,
                                 &new_rbSize);
    if (!success || new_tbs != retInfo->tb_size) {
931
      LOG_D(NR_MAC, "%s(): new TBsize %d of new TDA does not match old TBS %d\n", __func__, new_tbs, retInfo->tb_size);
932 933
      return false; /* the maximum TBsize we might have is smaller than what we need */
    }
934
    LOG_D(NR_MAC, "%s(): retransmission with TDA %d->%d and TBS %d -> %d\n", __func__, retInfo->time_domain_allocation, tda, retInfo->tb_size, new_tbs);
935 936 937 938 939 940 941 942
    /* we can allocate it. Overwrite the time_domain_allocation, the number
     * of RBs, and the new TB size. The rest is done below */
    retInfo->tb_size = new_tbs;
    retInfo->rbSize = new_rbSize;
    retInfo->time_domain_allocation = tda;
    sched_ctrl->pusch_semi_static = temp_ps;
  }

943
  /* Find a free CCE */
944
  const uint32_t Y = get_Y(sched_ctrl->search_space, slot, UE->rnti);
945 946 947 948 949 950 951 952 953
  uint8_t nr_of_candidates;
  for (int i=0; i<5; i++) {
    // for now taking the lowest value among the available aggregation levels
    find_aggregation_candidates(&sched_ctrl->aggregation_level,
                                &nr_of_candidates,
                                sched_ctrl->search_space,
                                1<<i);
    if(nr_of_candidates>0) break;
  }
Laurent THOMAS's avatar
Laurent THOMAS committed
954
  int CCEIndex = find_pdcch_candidate(nrmac,
955 956 957
                                      CC_id,
                                      sched_ctrl->aggregation_level,
                                      nr_of_candidates,
958
                                      &sched_ctrl->sched_pdcch,
959 960 961 962
                                      sched_ctrl->coreset,
                                      Y);

  if (CCEIndex<0) {
Laurent THOMAS's avatar
Laurent THOMAS committed
963
    LOG_D(NR_MAC, "%4d.%2d no free CCE for retransmission UL DCI UE %04x\n", frame, slot, UE->rnti);
964 965 966
    return false;
  }

967
  sched_ctrl->cce_index = CCEIndex;
Laurent THOMAS's avatar
Laurent THOMAS committed
968
  fill_pdcch_vrb_map(nrmac,
969
                     CC_id,
970
                     &sched_ctrl->sched_pdcch,
971 972 973
                     CCEIndex,
                     sched_ctrl->aggregation_level);

974 975 976 977 978 979 980 981 982
  /* frame/slot in sched_pusch has been set previously. In the following, we
   * overwrite the information in the retransmission information before storing
   * as the new scheduling instruction */
  retInfo->frame = sched_ctrl->sched_pusch.frame;
  retInfo->slot = sched_ctrl->sched_pusch.slot;
  /* Get previous PSUCH field info */
  sched_ctrl->sched_pusch = *retInfo;
  NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;

983
  LOG_D(NR_MAC,
Laurent THOMAS's avatar
Laurent THOMAS committed
984
        "%4d.%2d Allocate UL retransmission RNTI %04x sched %4d.%2d (%d RBs)\n",
985 986
        frame,
        slot,
Laurent THOMAS's avatar
Laurent THOMAS committed
987
        UE->rnti,
988 989 990 991 992 993 994 995 996 997
        sched_pusch->frame,
        sched_pusch->slot,
        sched_pusch->rbSize);

  sched_pusch->rbStart = rbStart;
  /* no need to recompute the TBS, it will be the same */

  /* Mark the corresponding RBs as used */
  n_rb_sched -= sched_pusch->rbSize;
  for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
francescomani's avatar
francescomani committed
998
    rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] ^= SL_to_bitmap(sched_ctrl->pusch_semi_static.startSymbolIndex, sched_ctrl->pusch_semi_static.nrOfSymbols);
999 1000 1001
  return true;
}

1002 1003
void update_ul_ue_R_Qm(NR_sched_pusch_t *sched_pusch, const NR_PUSCH_Config_t *pusch_Config, const int mcs_table) {

1004
  const int mcs = sched_pusch->mcs;
1005 1006
  sched_pusch->R = nr_get_code_rate_ul(mcs, mcs_table);
  sched_pusch->Qm = nr_get_Qm_ul(mcs, mcs_table);
1007

1008
  if (pusch_Config && pusch_Config->tp_pi2BPSK && ((mcs_table == 3 && mcs < 2) || (mcs_table == 4 && mcs < 6))) {
1009 1010 1011 1012 1013
    sched_pusch->R >>= 1;
    sched_pusch->Qm <<= 1;
  }
}

Laurent THOMAS's avatar
Laurent THOMAS committed
1014
uint32_t ul_pf_tbs[3][29]; // pre-computed, approximate TBS values for PF coefficient
Laurent THOMAS's avatar
Laurent THOMAS committed
1015 1016 1017 1018 1019 1020 1021 1022 1023
typedef struct UEsched_s {
  float coef;
  NR_UE_info_t * UE;
} UEsched_t;

static int comparator(const void *p, const void *q) {
  return ((UEsched_t*)p)->coef < ((UEsched_t*)q)->coef;
}

ChiehChun's avatar
ChiehChun committed
1024 1025 1026
void pf_ul(module_id_t module_id,
           frame_t frame,
           sub_frame_t slot,
Roberto Louro Magueta's avatar
Roberto Louro Magueta committed
1027
           NR_UE_info_t *UE_list[],
1028
           int max_num_ue,
ChiehChun's avatar
ChiehChun committed
1029
           int n_rb_sched,
1030
           uint16_t *rballoc_mask) {
ChiehChun's avatar
ChiehChun committed
1031 1032

  const int CC_id = 0;
1033 1034
  gNB_MAC_INST *nrmac = RC.nrmac[module_id];
  NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
1035
  const NR_SIB1_t *sib1 = RC.nrmac[module_id]->common_channels[0].sib1 ? RC.nrmac[module_id]->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL;
Laurent THOMAS's avatar
Laurent THOMAS committed
1036 1037
  
  const int min_rb = 5;
1038
  // UEs that could be scheduled
Laurent THOMAS's avatar
Laurent THOMAS committed
1039 1040 1041
  UEsched_t UE_sched[MAX_MOBILES_PER_GNB] = {0};
  int remainUEs=max_num_ue;
  int curUE=0;
ChiehChun's avatar
ChiehChun committed
1042 1043

  /* Loop UE_list to calculate throughput and coeff */
Laurent THOMAS's avatar
Laurent THOMAS committed
1044
  UE_iterator(UE_list, UE) {
1045

Laurent THOMAS's avatar
Laurent THOMAS committed
1046 1047
    if (UE->Msg4_ACKed != true)
      continue;
1048

Laurent THOMAS's avatar
Laurent THOMAS committed
1049 1050
    LOG_D(NR_MAC,"pf_ul: preparing UL scheduling for UE %04x\n",UE->rnti);
    NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
francescomani's avatar
francescomani committed
1051
    NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
1052

1053
    int rbStart = 0; // wrt BWP start
Eurecom's avatar
Eurecom committed
1054

francescomani's avatar
francescomani committed
1055
    const uint16_t bwpSize = current_BWP->BWPSize;
1056 1057
    NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
    NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static;
Laurent THOMAS's avatar
Laurent THOMAS committed
1058
    const NR_mac_dir_stats_t *stats = &UE->mac_stats.ul;
ChiehChun's avatar
ChiehChun committed
1059 1060

    /* Calculate throughput */
1061
    const float a = 0.0005f; // corresponds to 200ms window
Robert Schmidt's avatar
Robert Schmidt committed
1062
    const uint32_t b = stats->current_bytes;
Laurent THOMAS's avatar
Laurent THOMAS committed
1063
    UE->ul_thr_ue = (1 - a) * UE->ul_thr_ue + a * b;
ChiehChun's avatar
ChiehChun committed
1064

1065
    /* Check if retransmission is necessary */
1066
    sched_pusch->ul_harq_pid = sched_ctrl->retrans_ul_harq.head;
Laurent THOMAS's avatar
Laurent THOMAS committed
1067
    LOG_D(NR_MAC,"pf_ul: UE %04x harq_pid %d\n",UE->rnti,sched_pusch->ul_harq_pid);
1068 1069
    if (sched_pusch->ul_harq_pid >= 0) {
      /* Allocate retransmission*/
1070
      const int tda = get_ul_tda(nrmac, scc, sched_pusch->slot);
Laurent THOMAS's avatar
Laurent THOMAS committed
1071
      bool r = allocate_ul_retransmission(nrmac, frame, slot, rballoc_mask, &n_rb_sched, UE, sched_pusch->ul_harq_pid, sib1, scc, tda);
1072
      if (!r) {
Laurent THOMAS's avatar
Laurent THOMAS committed
1073
        LOG_D(NR_MAC, "%4d.%2d UL retransmission UE RNTI %04x can NOT be allocated\n", frame, slot, UE->rnti);
1074 1075
        continue;
      }
Laurent THOMAS's avatar
Laurent THOMAS committed
1076
      else LOG_D(NR_MAC,"%4d.%2d UL Retransmission UE RNTI %04x to be allocated, max_num_ue %d\n",frame,slot,UE->rnti,max_num_ue);
1077

1078
      /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
Laurent THOMAS's avatar
Laurent THOMAS committed
1079
      remainUEs--;
1080

1081 1082
      // we have filled all with mandatory retransmissions
      // no need to schedule new transmissions
Laurent THOMAS's avatar
Laurent THOMAS committed
1083
      if (remainUEs == 0)
1084 1085
	      return;

Laurent THOMAS's avatar
Laurent THOMAS committed
1086 1087
      continue;
    } 
1088 1089
    const int B = max(0, sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes);
    /* preprocessor computed sched_frame/sched_slot */
Laurent THOMAS's avatar
Laurent THOMAS committed
1090
    const bool do_sched = nr_UE_is_to_be_scheduled(scc, 0, UE, sched_pusch->frame, sched_pusch->slot, nrmac->ulsch_max_frame_inactivity);
1091

Laurent THOMAS's avatar
Laurent THOMAS committed
1092
    LOG_D(NR_MAC,"pf_ul: do_sched UE %04x => %s\n",UE->rnti,do_sched ? "yes" : "no");
1093
    if ((B == 0 && !do_sched) || (sched_ctrl->rrc_processing_timer > 0)) {
Robert Schmidt's avatar
Robert Schmidt committed
1094
      continue;
1095
    }
Robert Schmidt's avatar
Robert Schmidt committed
1096

Robert Schmidt's avatar
Robert Schmidt committed
1097 1098
    const NR_bler_options_t *bo = &nrmac->ul_bler;
    const int max_mcs = bo->max_mcs; /* no per-user maximum MCS yet */
1099 1100 1101 1102
    if (bo->harq_round_max == 1)
      sched_pusch->mcs = max_mcs;
    else
      sched_pusch->mcs = get_mcs_from_bler(bo, stats, &UE->UE_sched_ctrl.ul_bler_stats, max_mcs, frame);
Robert Schmidt's avatar
Robert Schmidt committed
1103

1104 1105 1106
    /* Schedule UE on SR or UL inactivity and no data (otherwise, will be scheduled
     * based on data to transmit) */
    if (B == 0 && do_sched) {
1107
      /* if no data, pre-allocate 5RB */
1108
      /* Find a free CCE */
1109
      const uint32_t Y = get_Y(sched_ctrl->search_space, slot, UE->rnti);
1110 1111 1112 1113 1114 1115 1116 1117 1118 1119
      uint8_t nr_of_candidates;
      for (int i=0; i<5; i++) {
        // for now taking the lowest value among the available aggregation levels
        find_aggregation_candidates(&sched_ctrl->aggregation_level,
                                    &nr_of_candidates,
                                    sched_ctrl->search_space,
                                    1<<i);
        if(nr_of_candidates>0) break;
      }
      int CCEIndex = find_pdcch_candidate(RC.nrmac[module_id],
Laurent THOMAS's avatar
Laurent THOMAS committed
1120 1121 1122 1123 1124 1125
					  CC_id,
					  sched_ctrl->aggregation_level,
					  nr_of_candidates,
					  &sched_ctrl->sched_pdcch,
					  sched_ctrl->coreset,
					  Y);
1126 1127

      if (CCEIndex<0) {
1128
        LOG_D(NR_MAC, "%4d.%2d no free CCE for UL DCI UE %04x (BSR 0)\n", frame, slot, UE->rnti);
1129 1130
        continue;
      }
1131

1132
      /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
Laurent THOMAS's avatar
Laurent THOMAS committed
1133
      remainUEs--;
1134 1135 1136

      // we have filled all with mandatory retransmissions
      // no need to schedule new transmissions
Laurent THOMAS's avatar
Laurent THOMAS committed
1137
      if (remainUEs == 0)
1138 1139
        return;

1140 1141
      /* Save PUSCH field */
      /* we want to avoid a lengthy deduction of DMRS and other parameters in
1142
       * every TTI if we can save it, so check whether TDA, or
1143
       * num_dmrs_cdm_grps_no_data has changed and only then recompute */
1144
      const uint8_t nrOfLayers = 1;
francescomani's avatar
francescomani committed
1145
      const int tda = get_ul_tda(nrmac, scc, sched_pusch->slot);
1146
      if (ps->time_domain_allocation != tda
francescomani's avatar
francescomani committed
1147
          || ps->nrOfLayers != nrOfLayers) {
francescomani's avatar
francescomani committed
1148
        nr_set_pusch_semi_static(current_BWP,
1149 1150
                                 scc,
                                 tda,
1151
                                 nrOfLayers,
1152
                                 ps);
1153
      }
1154

1155 1156
      LOG_D(NR_MAC,"Looking for min_rb %d RBs, starting at %d num_dmrs_cdm_grps_no_data %d\n",
            min_rb, rbStart, ps->num_dmrs_cdm_grps_no_data);
1157 1158
      const uint16_t slbitmap = SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols);
      while (rbStart < bwpSize && (rballoc_mask[rbStart] & slbitmap) != slbitmap)
1159 1160
        rbStart++;
      if (rbStart + min_rb >= bwpSize) {
Laurent THOMAS's avatar
Laurent THOMAS committed
1161 1162
        LOG_W(NR_MAC, "cannot allocate continuous UL data for RNTI %04x: no resources (rbStart %d, min_rb %d, bwpSize %d\n",
              UE->rnti,rbStart,min_rb,bwpSize);
1163 1164 1165
        return;
      }

francescomani's avatar
francescomani committed
1166 1167 1168 1169 1170 1171 1172
      sched_ctrl->cce_index = CCEIndex;
      fill_pdcch_vrb_map(RC.nrmac[module_id],
                         CC_id,
                         &sched_ctrl->sched_pdcch,
                         CCEIndex,
                         sched_ctrl->aggregation_level);

1173
      NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
Robert Schmidt's avatar
Robert Schmidt committed
1174
      sched_pusch->mcs = min(nrmac->min_grant_mcs, sched_pusch->mcs);
francescomani's avatar
francescomani committed
1175
      update_ul_ue_R_Qm(sched_pusch, current_BWP->pusch_Config, current_BWP->mcs_table);
1176 1177 1178 1179 1180 1181 1182 1183 1184
      sched_pusch->rbStart = rbStart;
      sched_pusch->rbSize = min_rb;
      sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm,
                                            sched_pusch->R,
                                            sched_pusch->rbSize,
                                            ps->nrOfSymbols,
                                            ps->N_PRB_DMRS * ps->num_dmrs_symb,
                                            0, // nb_rb_oh
                                            0,
1185
                                            ps->nrOfLayers)
1186 1187 1188 1189 1190
                             >> 3;

      /* Mark the corresponding RBs as used */
      n_rb_sched -= sched_pusch->rbSize;
      for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
1191
        rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] ^= slbitmap;
1192 1193

      continue;
1194
    }
1195 1196

    /* Create UE_sched for UEs eligibale for new data transmission*/
Robert Schmidt's avatar
Robert Schmidt committed
1197
    /* Calculate coefficient*/
francescomani's avatar
francescomani committed
1198
    const uint32_t tbs = ul_pf_tbs[current_BWP->mcs_table][sched_pusch->mcs];
Laurent THOMAS's avatar
Laurent THOMAS committed
1199 1200 1201 1202 1203 1204
    float coeff_ue = (float) tbs / UE->ul_thr_ue;
    LOG_D(NR_MAC,"rnti %04x b %d, ul_thr_ue %f, tbs %d, coeff_ue %f\n",
          UE->rnti, b, UE->ul_thr_ue, tbs, coeff_ue);
    UE_sched[curUE].coef=coeff_ue;
    UE_sched[curUE].UE=UE;
    curUE++;
1205 1206
  }

Laurent THOMAS's avatar
Laurent THOMAS committed
1207 1208 1209
  qsort(UE_sched, sizeof(*UE_sched), sizeofArray(UE_sched), comparator);
  UEsched_t *iterator=UE_sched;
  
1210
  const int min_rbSize = 5;
Robert Schmidt's avatar
Robert Schmidt committed
1211
  /* Loop UE_sched to find max coeff and allocate transmission */
Laurent THOMAS's avatar
Laurent THOMAS committed
1212
  while (remainUEs> 0 && n_rb_sched >= min_rbSize && iterator->UE != NULL) {
Robert Schmidt's avatar
Robert Schmidt committed
1213

Laurent THOMAS's avatar
Laurent THOMAS committed
1214
    NR_UE_sched_ctrl_t *sched_ctrl = &iterator->UE->UE_sched_ctrl;
1215

1216
    const uint32_t Y = get_Y(sched_ctrl->search_space, slot, iterator->UE->rnti);
1217 1218 1219 1220 1221 1222 1223
    uint8_t nr_of_candidates;
    for (int i=0; i<5; i++) {
      // for now taking the lowest value among the available aggregation levels
      find_aggregation_candidates(&sched_ctrl->aggregation_level,
                                  &nr_of_candidates,
                                  sched_ctrl->search_space,
                                  1<<i);
Laurent THOMAS's avatar
Laurent THOMAS committed
1224
      if(nr_of_candidates>0)
1225
        break;
1226 1227 1228 1229 1230
    }
    int CCEIndex = find_pdcch_candidate(RC.nrmac[module_id],
                                        CC_id,
                                        sched_ctrl->aggregation_level,
                                        nr_of_candidates,
1231
                                        &sched_ctrl->sched_pdcch,
1232 1233 1234
                                        sched_ctrl->coreset,
                                        Y);
    if (CCEIndex<0) {
Laurent THOMAS's avatar
Laurent THOMAS committed
1235 1236
      LOG_D(NR_MAC, "%4d.%2d no free CCE for UL DCI UE %04x\n", frame, slot, iterator->UE->rnti);
      iterator++;
1237 1238
      continue;
    }
Laurent THOMAS's avatar
Laurent THOMAS committed
1239
    else LOG_D(NR_MAC, "%4d.%2d free CCE for UL DCI UE %04x\n",frame,slot, iterator->UE->rnti);
1240

francescomani's avatar
francescomani committed
1241
    NR_UE_UL_BWP_t *current_BWP = &iterator->UE->current_UL_BWP;
1242

francescomani's avatar
francescomani committed
1243
    const uint16_t bwpSize = current_BWP->BWPSize;
Robert Schmidt's avatar
Robert Schmidt committed
1244
    NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
1245
    NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static;
ChiehChun's avatar
ChiehChun committed
1246

1247 1248
    /* Save PUSCH field */
    /* we want to avoid a lengthy deduction of DMRS and other parameters in
1249
     * every TTI if we can save it, so check whether TDA, or
1250
     * num_dmrs_cdm_grps_no_data has changed and only then recompute */
1251
    const uint8_t nrOfLayers = 1;
francescomani's avatar
francescomani committed
1252
    const int tda = get_ul_tda(nrmac, scc, sched_pusch->slot);
1253
    if (ps->time_domain_allocation != tda
francescomani's avatar
francescomani committed
1254
        || ps->nrOfLayers != nrOfLayers) {
francescomani's avatar
francescomani committed
1255
      nr_set_pusch_semi_static(current_BWP,
1256 1257
                               scc,
                               tda,
1258
                               nrOfLayers,
1259
                               ps);
1260
    }
francescomani's avatar
francescomani committed
1261
    update_ul_ue_R_Qm(sched_pusch, current_BWP->pusch_Config, current_BWP->mcs_table);
ChiehChun's avatar
ChiehChun committed
1262

francescomani's avatar
francescomani committed
1263
    int rbStart = 0;
1264 1265
    const uint16_t slbitmap = SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols);
    while (rbStart < bwpSize && (rballoc_mask[rbStart] & slbitmap) != slbitmap)
1266 1267 1268
      rbStart++;
    sched_pusch->rbStart = rbStart;
    uint16_t max_rbSize = 1;
1269
    while (rbStart + max_rbSize < bwpSize && (rballoc_mask[rbStart + max_rbSize] & slbitmap) == slbitmap)
1270 1271 1272
      max_rbSize++;

    if (rbStart + min_rb >= bwpSize) {
Laurent THOMAS's avatar
Laurent THOMAS committed
1273 1274
      LOG_W(NR_MAC, "cannot allocate UL data for RNTI %04x: no resources (rbStart %d, min_rb %d, bwpSize %d)\n",
	    iterator->UE->rnti,rbStart,min_rb,bwpSize);
1275 1276
      return;
    }
Laurent THOMAS's avatar
Laurent THOMAS committed
1277 1278
    else
      LOG_D(NR_MAC,"allocating UL data for RNTI %04x (rbStsart %d, min_rb %d, bwpSize %d)\n", iterator->UE->rnti,rbStart,min_rb,bwpSize);
1279

1280
    /* Calculate the current scheduling bytes and the necessary RBs */
ChiehChun's avatar
ChiehChun committed
1281
    const int B = cmax(sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, 0);
1282 1283
    uint16_t rbSize = 0;
    uint32_t TBS = 0;
1284

1285 1286
    nr_find_nb_rb(sched_pusch->Qm,
                  sched_pusch->R,
1287
                  1, // layers
1288 1289 1290
                  ps->nrOfSymbols,
                  ps->N_PRB_DMRS * ps->num_dmrs_symb,
                  B,
1291
                  min_rbSize,
1292 1293 1294 1295 1296
                  max_rbSize,
                  &TBS,
                  &rbSize);
    sched_pusch->rbSize = rbSize;
    sched_pusch->tb_size = TBS;
1297
    LOG_D(NR_MAC,"rbSize %d (max_rbSize %d), TBS %d, est buf %d, sched_ul %d, B %d, CCE %d, num_dmrs_symb %d, N_PRB_DMRS %d\n",
Eurecom's avatar
Eurecom committed
1298
          rbSize, max_rbSize,sched_pusch->tb_size, sched_ctrl->estimated_ul_buffer, sched_ctrl->sched_ul_bytes, B,sched_ctrl->cce_index,ps->num_dmrs_symb,ps->N_PRB_DMRS);
ChiehChun's avatar
ChiehChun committed
1299 1300

    /* Mark the corresponding RBs as used */
1301 1302 1303 1304

    sched_ctrl->cce_index = CCEIndex;
    fill_pdcch_vrb_map(RC.nrmac[module_id],
                       CC_id,
1305
                       &sched_ctrl->sched_pdcch,
1306 1307 1308
                       CCEIndex,
                       sched_ctrl->aggregation_level);

1309
    n_rb_sched -= sched_pusch->rbSize;
ChiehChun's avatar
ChiehChun committed
1310
    for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
1311
      rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] ^= slbitmap;
1312

Laurent THOMAS's avatar
Laurent THOMAS committed
1313 1314 1315
    /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
    remainUEs--;
    iterator++;
1316 1317 1318
  }
}

1319 1320
bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot)
{
1321 1322 1323
  gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
  NR_COMMON_channels_t *cc = nr_mac->common_channels;
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
1324 1325
  const NR_SIB1_t *sib1 = nr_mac->common_channels[0].sib1 ? nr_mac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL;
  NR_ServingCellConfigCommonSIB_t *scc_sib1 = sib1 ? sib1->servingCellConfigCommon : NULL;
1326 1327 1328

  AssertFatal(scc!=NULL || scc_sib1!=NULL,"We need one serving cell config common\n");

1329
  // no UEs
Laurent THOMAS's avatar
Laurent THOMAS committed
1330
  if (nr_mac->UE_info.list[0] == NULL)
1331
    return false;
1332 1333 1334

  const int CC_id = 0;

1335 1336 1337 1338
  /* Get the K2 for first UE to compute offset. The other UEs are guaranteed to
   * have the same K2 (we don't support multiple/different K2s via different
   * TDAs yet). If the TDA is negative, it means that there is no UL slot to
   * schedule now (slot + k2 is not UL slot) */
Laurent THOMAS's avatar
Laurent THOMAS committed
1339
  NR_UE_sched_ctrl_t *sched_ctrl = &nr_mac->UE_info.list[0]->UE_sched_ctrl;
francescomani's avatar
francescomani committed
1340 1341
  NR_UE_UL_BWP_t *current_BWP = &nr_mac->UE_info.list[0]->current_UL_BWP;
  int mu = current_BWP->scs;
francescomani's avatar
francescomani committed
1342
  const int temp_tda = get_ul_tda(nr_mac, scc, slot);
francescomani's avatar
francescomani committed
1343
  int K2 = get_K2(current_BWP->tdaList, temp_tda, mu);
luis_pereira87's avatar
luis_pereira87 committed
1344
  const int sched_frame = (frame + (slot + K2 >= nr_slots_per_frame[mu])) & 1023;
ChiehChun's avatar
ChiehChun committed
1345
  const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
francescomani's avatar
francescomani committed
1346 1347 1348
  const int tda = get_ul_tda(nr_mac, scc, sched_slot);
  if (tda < 0)
    return false;
francescomani's avatar
francescomani committed
1349
  DevAssert(K2 == get_K2(current_BWP->tdaList, tda, mu));
1350

1351
  if (!is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot))
1352
    return false;
1353

francescomani's avatar
francescomani committed
1354 1355 1356 1357 1358 1359 1360
  bool is_mixed_slot = false;
  const NR_TDD_UL_DL_Pattern_t *tdd =
      scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;

  if (tdd)
    is_mixed_slot = is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[sched_slot / 64], sched_slot) &&
                    is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot);
1361 1362

  // FIXME: Avoid mixed slots for initialUplinkBWP
francescomani's avatar
francescomani committed
1363
  if (current_BWP->bwp_id==0 && is_mixed_slot)
1364 1365
    return false;

1366
  // Avoid slots with the SRS
Laurent THOMAS's avatar
Laurent THOMAS committed
1367 1368
  UE_iterator(nr_mac->UE_info.list, UE) {
    NR_sched_srs_t sched_srs = UE->UE_sched_ctrl.sched_srs;
1369 1370 1371 1372 1373
    if(sched_srs.srs_scheduled && sched_srs.frame==sched_frame && sched_srs.slot==sched_slot) {
      return false;
    }
  }

1374 1375
  sched_ctrl->sched_pusch.slot = sched_slot;
  sched_ctrl->sched_pusch.frame = sched_frame;
Laurent THOMAS's avatar
Laurent THOMAS committed
1376 1377
  UE_iterator(nr_mac->UE_info.list, UE2) {
    NR_UE_sched_ctrl_t *sched_ctrl = &UE2->UE_sched_ctrl;
francescomani's avatar
francescomani committed
1378
    AssertFatal(K2 == get_K2(current_BWP->tdaList, tda, mu),
Laurent THOMAS's avatar
Laurent THOMAS committed
1379
                "Different K2, %d(UE%d) != %ld(UE%04x)\n",
francescomani's avatar
francescomani committed
1380
		K2, 0, get_K2(current_BWP->tdaList, tda, mu), UE2->rnti);
ChiehChun's avatar
ChiehChun committed
1381 1382
    sched_ctrl->sched_pusch.slot = sched_slot;
    sched_ctrl->sched_pusch.frame = sched_frame;
1383
  }
Robert Schmidt's avatar
Robert Schmidt committed
1384

1385 1386 1387
  /* Change vrb_map_UL to rballoc_mask: check which symbols per RB (in
   * vrb_map_UL) overlap with the "default" tda and exclude those RBs.
   * Calculate largest contiguous RBs */
1388 1389
  uint16_t *vrb_map_UL =
      &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * MAX_BWP_SIZE];
1390

francescomani's avatar
francescomani committed
1391 1392
  const uint16_t bwpSize = current_BWP->BWPSize;
  const uint16_t bwpStart = current_BWP->BWPStart;
1393

francescomani's avatar
francescomani committed
1394
  const int startSymbolAndLength = current_BWP->tdaList->list.array[tda]->startSymbolAndLength;
1395 1396
  int startSymbolIndex, nrOfSymbols;
  SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols);
1397
  const uint16_t symb = SL_to_bitmap(startSymbolIndex, nrOfSymbols);
1398

1399
  int st = 0, e = 0, len = 0;
1400

1401
  for (int i = 0; i < bwpSize; i++) {
1402
    while ((vrb_map_UL[bwpStart + i] & symb) != 0 && i < bwpSize)
1403 1404
      i++;
    st = i;
1405
    while ((vrb_map_UL[bwpStart + i] & symb) == 0 && i < bwpSize)
1406 1407 1408 1409 1410
      i++;
    if (i - st > len) {
      len = i - st;
      e = i - 1;
    }
1411
  }
1412 1413
  st = e - len + 1;

Raymond Knopp's avatar
Raymond Knopp committed
1414
  LOG_D(NR_MAC,"UL %d.%d : start_prb %d, end PRB %d\n",frame,slot,st,e);
1415
  
1416
  uint16_t rballoc_mask[bwpSize];
1417 1418 1419

  /* Calculate mask: if any RB in vrb_map_UL is blocked (1), the current RB will be 0 */
  for (int i = 0; i < bwpSize; i++)
1420
    rballoc_mask[i] = (i >= st && i <= e)*SL_to_bitmap(startSymbolIndex, nrOfSymbols);
1421

ChiehChun's avatar
ChiehChun committed
1422 1423 1424 1425
  /* proportional fair scheduling algorithm */
  pf_ul(module_id,
        frame,
        slot,
Laurent THOMAS's avatar
Laurent THOMAS committed
1426
        nr_mac->UE_info.list,
1427
        2,
1428
        len,
1429
        rballoc_mask);
1430
  return true;
1431 1432
}

1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446
nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(module_id_t module_id, int CC_id)
{
  /* in the PF algorithm, we have to use the TBsize to compute the coefficient.
   * This would include the number of DMRS symbols, which in turn depends on
   * the time domain allocation. In case we are in a mixed slot, we do not want
   * to recalculate all these values, and therefore we provide a look-up table
   * which should approximately(!) give us the TBsize. In particular, the
   * number of symbols, the number of DMRS symbols, and the exact Qm and R, are
   * not correct*/
  for (int mcsTableIdx = 0; mcsTableIdx < 3; ++mcsTableIdx) {
    for (int mcs = 0; mcs < 29; ++mcs) {
      if (mcs > 27 && mcsTableIdx == 1)
        continue;
      const uint8_t Qm = nr_get_Qm_dl(mcs, mcsTableIdx);
1447
      const uint16_t R = nr_get_code_rate_ul(mcs, mcsTableIdx);
1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465
      /* note: we do not update R/Qm based on low MCS or pi2BPSK */
      ul_pf_tbs[mcsTableIdx][mcs] = nr_compute_tbs(Qm,
                                                   R,
                                                   1, /* rbSize */
                                                   10, /* hypothetical number of slots */
                                                   0, /* N_PRB_DMRS * N_DMRS_SLOT */
                                                   0 /* N_PRB_oh, 0 for initialBWP */,
                                                   0 /* tb_scaling */,
                                                   1 /* nrOfLayers */)
                                    >> 3;
    }
  }
  return nr_fr1_ulsch_preprocessor;
}

void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot)
{
  gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
1466 1467
  /* Uplink data ONLY can be scheduled when the current slot is downlink slot,
   * because we have to schedule the DCI0 first before schedule uplink data */
1468
  if (!is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slot / 64], slot)) {
1469
    LOG_D(NR_MAC, "Current slot %d is NOT DL slot, cannot schedule DCI0 for UL data\n", slot);
1470 1471
    return;
  }
1472
  bool do_sched = RC.nrmac[module_id]->pre_processor_ul(module_id, frame, slot);
1473 1474
  if (!do_sched)
    return;
1475

1476 1477 1478 1479 1480 1481 1482
  const int CC_id = 0;
  nfapi_nr_ul_dci_request_t *ul_dci_req = &RC.nrmac[module_id]->UL_dci_req[CC_id];
  ul_dci_req->SFN = frame;
  ul_dci_req->Slot = slot;
  /* a PDCCH PDU groups DCIs per BWP and CORESET. Save a pointer to each
   * allocated PDCCH so we can easily allocate UE's DCIs independent of any
   * CORESET order */
1483 1484
  nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_coreset[MAX_NUM_CORESET] = {0};

1485

1486
  NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon;
Laurent THOMAS's avatar
Laurent THOMAS committed
1487
  NR_UEs_t *UE_info = &RC.nrmac[module_id]->UE_info;
1488
  const NR_SIB1_t *sib1 = RC.nrmac[module_id]->common_channels[0].sib1 ? RC.nrmac[module_id]->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL;
Laurent THOMAS's avatar
Laurent THOMAS committed
1489 1490
  UE_iterator( UE_info->list, UE) {
    NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
1491
    if (sched_ctrl->ul_failure == 1 && get_softmodem_params()->phy_test==0) continue;
1492

Laurent THOMAS's avatar
Laurent THOMAS committed
1493
    NR_CellGroupConfig_t *cg = UE->CellGroup;
1494
    NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
1495

Laurent THOMAS's avatar
Laurent THOMAS committed
1496
    UE->mac_stats.ul.current_bytes = 0;
1497

1498 1499
    /* dynamic PUSCH values (RB alloc, MCS, hence R, Qm, TBS) that change in
     * every TTI are pre-populated by the preprocessor and used below */
Robert Schmidt's avatar
Robert Schmidt committed
1500
    NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
Laurent THOMAS's avatar
Laurent THOMAS committed
1501
    LOG_D(NR_MAC,"UE %04x : sched_pusch->rbSize %d\n",UE->rnti,sched_pusch->rbSize);
Robert Schmidt's avatar
Robert Schmidt committed
1502
    if (sched_pusch->rbSize <= 0)
1503 1504
      continue;

Laurent THOMAS's avatar
Laurent THOMAS committed
1505
    uint16_t rnti = UE->rnti;
Robert Schmidt's avatar
Robert Schmidt committed
1506
    sched_ctrl->SR = false;
1507

1508 1509 1510 1511 1512
    int8_t harq_id = sched_pusch->ul_harq_pid;
    if (harq_id < 0) {
      /* PP has not selected a specific HARQ Process, get a new one */
      harq_id = sched_ctrl->available_ul_harq.head;
      AssertFatal(harq_id >= 0,
Laurent THOMAS's avatar
Laurent THOMAS committed
1513 1514
                  "no free HARQ process available for UE %04x\n",
                  UE->rnti);
1515
      remove_front_nr_list(&sched_ctrl->available_ul_harq);
1516
      sched_pusch->ul_harq_pid = harq_id;
1517 1518 1519 1520 1521 1522 1523 1524 1525
    } else {
      /* PP selected a specific HARQ process. Check whether it will be a new
       * transmission or a retransmission, and remove from the corresponding
       * list */
      if (sched_ctrl->ul_harq_processes[harq_id].round == 0)
        remove_nr_list(&sched_ctrl->available_ul_harq, harq_id);
      else
        remove_nr_list(&sched_ctrl->retrans_ul_harq, harq_id);
    }
Robert Schmidt's avatar
Robert Schmidt committed
1526
    NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[harq_id];
1527 1528 1529 1530
    DevAssert(!cur_harq->is_waiting);
    add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id);
    cur_harq->feedback_slot = sched_pusch->slot;
    cur_harq->is_waiting = true;
Robert Schmidt's avatar
Robert Schmidt committed
1531

Robert Schmidt's avatar
Robert Schmidt committed
1532 1533
    int rnti_types[2] = { NR_RNTI_C, 0 };

1534 1535
    /* pre-computed PUSCH values that only change if time domain allocation,
     * DCI format, or DMRS parameters change. Updated in the preprocessor
1536 1537
     * through nr_set_pusch_semi_static() */
    NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static;
1538

1539
    /* Statistics */
1540
    AssertFatal(cur_harq->round < nr_mac->ul_bler.harq_round_max, "Indexing ulsch_rounds[%d] is out of bounds\n", cur_harq->round);
Laurent THOMAS's avatar
Laurent THOMAS committed
1541
    UE->mac_stats.ul.rounds[cur_harq->round]++;
1542
    if (cur_harq->round == 0) {
Laurent THOMAS's avatar
Laurent THOMAS committed
1543
      UE->mac_stats.ulsch_total_bytes_scheduled += sched_pusch->tb_size;
1544 1545 1546
      /* Save information on MCS, TBS etc for the current initial transmission
       * so we have access to it when retransmitting */
      cur_harq->sched_pusch = *sched_pusch;
1547 1548 1549
      /* save which time allocation has been used, to be used on
       * retransmissions */
      cur_harq->sched_pusch.time_domain_allocation = ps->time_domain_allocation;
1550
      sched_ctrl->sched_ul_bytes += sched_pusch->tb_size;
1551
    } else {
1552
      LOG_D(NR_MAC,
1553
            "%d.%2d UL retransmission RNTI %04x sched %d.%2d HARQ PID %d round %d NDI %d\n",
1554 1555 1556 1557 1558
            frame,
            slot,
            rnti,
            sched_pusch->frame,
            sched_pusch->slot,
1559 1560 1561
            harq_id,
            cur_harq->round,
            cur_harq->ndi);
1562
    }
Laurent THOMAS's avatar
Laurent THOMAS committed
1563
    UE->mac_stats.ul.current_bytes = sched_pusch->tb_size;
1564 1565
    sched_ctrl->last_ul_frame = sched_pusch->frame;
    sched_ctrl->last_ul_slot = sched_pusch->slot;
1566

rmagueta's avatar
rmagueta committed
1567
    LOG_D(NR_MAC,
1568
          "ULSCH/PUSCH: %4d.%2d RNTI %04x UL sched %4d.%2d DCI L %d start %2d RBS %3d startSymbol %2d nb_symbol %2d dmrs_pos %x MCS %2d nrOfLayers %2d num_dmrs_cdm_grps_no_data %2d TBS %4d HARQ PID %2d round %d RV %d NDI %d est %6d sched %6d est BSR %6d TPC %d\n",
1569 1570 1571 1572 1573
          frame,
          slot,
          rnti,
          sched_pusch->frame,
          sched_pusch->slot,
Eurecom's avatar
Eurecom committed
1574
          sched_ctrl->aggregation_level,
1575 1576
          sched_pusch->rbStart,
          sched_pusch->rbSize,
1577 1578
          ps->startSymbolIndex,
          ps->nrOfSymbols,
1579
          ps->ul_dmrs_symb_pos,
1580
          sched_pusch->mcs,
1581 1582
          ps->nrOfLayers,
          ps->num_dmrs_cdm_grps_no_data,
1583 1584 1585
          sched_pusch->tb_size,
          harq_id,
          cur_harq->round,
1586
          nr_rv_round_map[cur_harq->round%4],
1587 1588 1589
          cur_harq->ndi,
          sched_ctrl->estimated_ul_buffer,
          sched_ctrl->sched_ul_bytes,
1590 1591
          sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes,
          sched_ctrl->tpc0);
1592

1593
    /* PUSCH in a later slot, but corresponding DCI now! */
Robert Schmidt's avatar
Robert Schmidt committed
1594 1595 1596
    nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_id]->UL_tti_req_ahead[0][sched_pusch->slot];
    AssertFatal(future_ul_tti_req->SFN == sched_pusch->frame
                && future_ul_tti_req->Slot == sched_pusch->slot,
1597 1598 1599 1600
                "%d.%d future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n",
                frame, slot,
                future_ul_tti_req->SFN,
                future_ul_tti_req->Slot,
Robert Schmidt's avatar
Robert Schmidt committed
1601 1602
                sched_pusch->frame,
                sched_pusch->slot);
1603 1604 1605
    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);
1606 1607 1608 1609 1610 1611
    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));
    future_ul_tti_req->n_pdus += 1;

1612
    LOG_D(NR_MAC, "%4d.%2d Scheduling UE specific PUSCH for sched %d.%d, ul_tti_req %d.%d\n", frame, slot,
1613
    sched_pusch->frame,sched_pusch->slot,future_ul_tti_req->SFN,future_ul_tti_req->Slot);
1614 1615 1616 1617 1618

    pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA;
    pusch_pdu->rnti = rnti;
    pusch_pdu->handle = 0; //not yet used

1619
    /* FAPI: BWP */
1620

1621 1622 1623
    pusch_pdu->bwp_size  = current_BWP->BWPSize;
    pusch_pdu->bwp_start = current_BWP->BWPStart;
    pusch_pdu->subcarrier_spacing = current_BWP->scs;
1624 1625
    pusch_pdu->cyclic_prefix = 0;

1626
    /* FAPI: PUSCH information always included */
1627
    pusch_pdu->target_code_rate = sched_pusch->R;
1628 1629
    pusch_pdu->qam_mod_order = sched_pusch->Qm;
    pusch_pdu->mcs_index = sched_pusch->mcs;
1630 1631 1632 1633
    pusch_pdu->mcs_table = current_BWP->mcs_table;
    pusch_pdu->transform_precoding = current_BWP->transform_precoding;
    if (current_BWP->pusch_Config && current_BWP->pusch_Config->dataScramblingIdentityPUSCH)
      pusch_pdu->data_scrambling_id = *current_BWP->pusch_Config->dataScramblingIdentityPUSCH;
1634 1635
    else
      pusch_pdu->data_scrambling_id = *scc->physCellId;
1636 1637
    pusch_pdu->nrOfLayers = ps->nrOfLayers;
    pusch_pdu->num_dmrs_cdm_grps_no_data = ps->num_dmrs_cdm_grps_no_data;
1638

1639
    /* FAPI: DMRS */
1640 1641
    pusch_pdu->ul_dmrs_symb_pos = ps->ul_dmrs_symb_pos;
    pusch_pdu->dmrs_config_type = ps->dmrs_config_type;
1642
    if (pusch_pdu->transform_precoding) { // transform precoding disabled
1643 1644
      long *scramblingid=NULL;
      if (ps->NR_DMRS_UplinkConfig && pusch_pdu->scid == 0)
1645
        scramblingid = ps->NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0;
1646
      else if (ps->NR_DMRS_UplinkConfig)
1647
        scramblingid = ps->NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID1;
1648 1649 1650 1651 1652 1653 1654
      if (scramblingid == NULL)
        pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId;
      else
        pusch_pdu->ul_dmrs_scrambling_id = *scramblingid;
    }
    else {
      pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId;
1655
      if (ps->NR_DMRS_UplinkConfig && ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity != NULL)
1656
        pusch_pdu->pusch_identity = *ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity;
1657
      else if (ps->NR_DMRS_UplinkConfig)
1658 1659
        pusch_pdu->pusch_identity = *scc->physCellId;
    }
1660
    pusch_pdu->scid = 0;      // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1]
1661
    pusch_pdu->num_dmrs_cdm_grps_no_data = ps->num_dmrs_cdm_grps_no_data;
1662
    pusch_pdu->dmrs_ports = ((1<<ps->nrOfLayers) - 1);
1663

1664 1665 1666 1667 1668
    /* FAPI: Pusch Allocation in frequency domain */
    pusch_pdu->resource_alloc = 1; //type 1
    pusch_pdu->rb_start = sched_pusch->rbStart;
    pusch_pdu->rb_size = sched_pusch->rbSize;
    pusch_pdu->vrb_to_prb_mapping = 0;
1669
    if (current_BWP->pusch_Config==NULL || current_BWP->pusch_Config->frequencyHopping==NULL)
1670 1671 1672 1673 1674
      pusch_pdu->frequency_hopping = 0;
    else
      pusch_pdu->frequency_hopping = 1;

    /* FAPI: Resource Allocation in time domain */
1675 1676
    pusch_pdu->start_symbol_index = ps->startSymbolIndex;
    pusch_pdu->nr_of_symbols = ps->nrOfSymbols;
1677 1678

    /* PUSCH PDU */
1679
    AssertFatal(cur_harq->round < nr_mac->ul_bler.harq_round_max, "Indexing nr_rv_round_map[%d] is out of bounds\n", cur_harq->round%4);
1680
    pusch_pdu->pusch_data.rv_index = nr_rv_round_map[cur_harq->round%4];
1681 1682
    pusch_pdu->pusch_data.harq_process_id = harq_id;
    pusch_pdu->pusch_data.new_data_indicator = cur_harq->ndi;
1683
    pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size;
1684 1685
    pusch_pdu->pusch_data.num_cb = 0; //CBG not supported

1686 1687
    pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = 0;

1688
    LOG_D(NR_MAC,"PUSCH PDU : data_scrambling_identity %x, dmrs_scrambling_id %x\n",pusch_pdu->data_scrambling_id,pusch_pdu->ul_dmrs_scrambling_id);
1689 1690 1691 1692 1693 1694 1695 1696
    /* TRANSFORM PRECODING --------------------------------------------------------*/

    if (pusch_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled){

      // U as specified in section 6.4.1.1.1.2 in 38.211, if sequence hopping and group hopping are disabled
      pusch_pdu->dfts_ofdm.low_papr_group_number = pusch_pdu->pusch_identity % 30;

      // V as specified in section 6.4.1.1.1.2 in 38.211 V = 0 if sequence hopping and group hopping are disabled
1697 1698
      if ((ps->NR_DMRS_UplinkConfig==NULL) || ((ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceGroupHopping == NULL) &&
					       (ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceHopping == NULL)))
1699 1700 1701 1702
        pusch_pdu->dfts_ofdm.low_papr_sequence_number = 0;
      else
        AssertFatal(1==0,"SequenceGroupHopping or sequenceHopping are NOT Supported\n");

1703
      LOG_D(NR_MAC,"TRANSFORM PRECODING IS ENABLED. CDM groups: %d, U: %d MCS table: %d\n", pusch_pdu->num_dmrs_cdm_grps_no_data, pusch_pdu->dfts_ofdm.low_papr_group_number, current_BWP->mcs_table);
1704 1705 1706 1707
    }

    /*-----------------------------------------------------------------------------*/

1708
    /* PUSCH PTRS */
1709
    if (ps->NR_DMRS_UplinkConfig && ps->NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) {
1710
      bool valid_ptrs_setup = false;
1711
      pusch_pdu->pusch_ptrs.ptrs_ports_list   = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t));
1712 1713 1714 1715 1716 1717 1718 1719
      valid_ptrs_setup = set_ul_ptrs_values(ps->NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup,
                                            pusch_pdu->rb_size, pusch_pdu->mcs_index, pusch_pdu->mcs_table,
                                            &pusch_pdu->pusch_ptrs.ptrs_freq_density,&pusch_pdu->pusch_ptrs.ptrs_time_density,
                                            &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset,&pusch_pdu->pusch_ptrs.num_ptrs_ports,
                                            &pusch_pdu->pusch_ptrs.ul_ptrs_power, pusch_pdu->nr_of_symbols);
      if (valid_ptrs_setup==true) {
        pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS
      }
1720 1721 1722 1723
    }
    else{
      pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS
    }
1724

1725 1726
    /* look up the PDCCH PDU for this BWP and CORESET. If it does not exist,
     * create it */
1727 1728
    NR_SearchSpace_t *ss = sched_ctrl->search_space;
    NR_ControlResourceSet_t *coreset = sched_ctrl->coreset;
1729
    const int coresetid = coreset->controlResourceSetId;
1730
    nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = pdcch_pdu_coreset[coresetid];
1731 1732 1733 1734 1735 1736 1737
    if (!pdcch_pdu) {
      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 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15;
      ul_dci_req->numPdus += 1;
1738
      nr_configure_pdcch(pdcch_pdu, coreset, false, &sched_ctrl->sched_pdcch);
1739
      pdcch_pdu_coreset[coresetid] = pdcch_pdu;
1740
    }
1741

Laurent THOMAS's avatar
Laurent THOMAS committed
1742
    LOG_D(NR_MAC,"Configuring ULDCI/PDCCH in %d.%d at CCE %d, rnti %04x\n", frame,slot,sched_ctrl->cce_index,rnti);
1743

1744 1745 1746 1747
    /* Fill PDCCH DL DCI PDU */
    nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu->dci_pdu[pdcch_pdu->numDlDci];
    pdcch_pdu->numDlDci++;
    dci_pdu->RNTI = rnti;
1748 1749 1750
    if (coreset->pdcch_DMRS_ScramblingID &&
        ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) {
      dci_pdu->ScramblingId = *coreset->pdcch_DMRS_ScramblingID;
1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762
      dci_pdu->ScramblingRNTI = rnti;
    } else {
      dci_pdu->ScramblingId = *scc->physCellId;
      dci_pdu->ScramblingRNTI = 0;
    }
    dci_pdu->AggregationLevel = sched_ctrl->aggregation_level;
    dci_pdu->CceIndex = sched_ctrl->cce_index;
    dci_pdu->beta_PDCCH_1_0 = 0;
    dci_pdu->powerControlOffsetSS = 1;

    dci_pdu_rel15_t uldci_payload;
    memset(&uldci_payload, 0, sizeof(uldci_payload));
1763

1764
    config_uldci(sib1,
1765
                 scc,
1766
                 pusch_pdu,
1767
                 &uldci_payload,
1768
                 ps->time_domain_allocation,
Laurent THOMAS's avatar
Laurent THOMAS committed
1769
                 UE->UE_sched_ctrl.tpc0,
1770
                 current_BWP);
1771
    fill_dci_pdu_rel15(scc,
1772
                       cg,
1773
                       &UE->current_DL_BWP,
1774 1775
                       dci_pdu,
                       &uldci_payload,
1776
                       current_BWP->dci_format,
1777
                       rnti_types[0],
1778
                       pusch_pdu->bwp_size,
1779
                       current_BWP->bwp_id,
1780
                       coreset,
1781
                       nr_mac->cset0_bwp_size);
1782

Robert Schmidt's avatar
Robert Schmidt committed
1783
    memset(sched_pusch, 0, sizeof(*sched_pusch));
1784
  }
1785
}