gNB_scheduler_ulsch.c 54.7 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

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
//38.321 Table 6.1.3.1-1
const uint32_t NR_SHORT_BSR_TABLE[32] = {
    0,    10,    14,    20,    28,     38,     53,     74,
  102,   142,   198,   276,   384,    535,    745,   1038,
 1446,  2014,  2806,  3909,  5446,   7587,  10570,  14726,
20516, 28581, 39818, 55474, 77284, 107669, 150000, 300000
};

//38.321 Table 6.1.3.1-2
const uint32_t NR_LONG_BSR_TABLE[256] ={
       0,       10,       11,       12,       13,       14,       15,       16,       17,       18,       19,       20,       22,       23,        25,         26,
      28,       30,       32,       34,       36,       38,       40,       43,       46,       49,       52,       55,       59,       62,        66,         71,
      75,       80,       85,       91,       97,      103,      110,      117,      124,      132,      141,      150,      160,      170,       181,        193,
     205,      218,      233,      248,      264,      281,      299,      318,      339,      361,      384,      409,      436,      464,       494,        526,
     560,      597,      635,      677,      720,      767,      817,      870,      926,      987,     1051,     1119,     1191,     1269,      1351,       1439,
    1532,     1631,     1737,     1850,     1970,     2098,     2234,     2379,     2533,     2698,     2873,     3059,     3258,     3469,      3694,       3934,
    4189,     4461,     4751,     5059,     5387,     5737,     6109,     6506,     6928,     7378,     7857,     8367,     8910,     9488,     10104,      10760,
   11458,    12202,    12994,    13838,    14736,    15692,    16711,    17795,    18951,    20181,    21491,    22885,    24371,    25953,     27638,      29431,
   31342,    33376,    35543,    37850,    40307,    42923,    45709,    48676,    51836,    55200,    58784,    62599,    66663,    70990,     75598,      80505,
   85730,    91295,    97221,   103532,   110252,   117409,   125030,   133146,   141789,   150992,   160793,   171231,   182345,   194182,    206786,     220209,
  234503,   249725,   265935,   283197,   301579,   321155,   342002,   364202,   387842,   413018,   439827,   468377,   498780,   531156,    565634,     602350,
  641449,   683087,   727427,   774645,   824928,   878475,   935498,   996222,  1060888,  1129752,  1203085,  1281179,  1364342,  1452903,   1547213,    1647644,
 1754595,  1868488,  1989774,  2118933,  2256475,  2402946,  2558924,  2725027,  2901912,  3090279,  3290873,  3504487,  3731968,  3974215,   4232186,    4506902,
 4799451,  5110989,  5442750,  5796046,  6172275,  6572925,  6999582,  7453933,  7937777,  8453028,  9001725,  9586039, 10208280, 10870913,  11576557,   12328006,
13128233, 13980403, 14887889, 15854280, 16883401, 17979324, 19146385, 20389201, 21712690, 23122088, 24622972, 26221280, 27923336, 29735875,  31666069,   33721553,
35910462, 38241455, 40723756, 43367187, 46182206, 49179951, 52372284, 55771835, 59392055, 63247269, 67352729, 71724679, 76380419, 81338368, 162676736, 4294967295
};
63

64 65
void nr_process_mac_pdu(
    module_id_t module_idP,
66
    rnti_t rnti,
67 68 69 70 71
    uint8_t CC_id,
    frame_t frameP,
    uint8_t *pduP,
    uint16_t mac_pdu_len)
{
cig's avatar
cig committed
72

73 74
    // This function is adapting code from the old
    // parse_header(...) and ue_send_sdu(...) functions of OAI LTE
cig's avatar
cig committed
75 76 77 78 79

    uint8_t *pdu_ptr = pduP, rx_lcid, done = 0;
    int pdu_len = mac_pdu_len;
    uint16_t mac_ce_len, mac_subheader_len, mac_sdu_len;

80 81 82
    NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info;
    int UE_id = find_nr_UE_id(module_idP, rnti);
    if (UE_id == -1) {
83
      LOG_E(NR_MAC, "%s() UE_id == -1\n",__func__);
84 85 86
      return;
    }
    NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
cig's avatar
cig committed
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
    //  For both DL/UL-SCH
    //  Except:
    //   - UL/DL-SCH: fixed-size MAC CE(known by LCID)
    //   - UL/DL-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 both DL/UL-SCH
    //  For:
    //   - UL/DL-SCH: fixed-size MAC CE(known by LCID)
    //   - UL/DL-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: lenght of L is 0:8 or 1:16 bits wide
    //  R: Reserved bit, set to zero.

    while (!done && pdu_len > 0){
113 114 115
        mac_ce_len = 0;
        mac_subheader_len = 1; //  default to fixed-length subheader = 1-oct
        mac_sdu_len = 0;
cig's avatar
cig committed
116 117
        rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID;

118
        LOG_D(NR_MAC, "LCID received at gNB side: %d \n", rx_lcid);
119

ChiehChun's avatar
ChiehChun committed
120
        unsigned char *ce_ptr;
121
        int n_Lcg = 0;
ChiehChun's avatar
ChiehChun committed
122

cig's avatar
cig committed
123
        switch(rx_lcid){
124 125 126
            //  MAC CE

            /*#ifdef DEBUG_HEADER_PARSING
127
              LOG_D(NR_MAC, "[UE] LCID %d, PDU length %d\n", ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID, pdu_len);
128
            #endif*/
129 130 131 132 133 134 135
        case UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY:
              // 38.321 Ch6.1.3.20
              mac_ce_len = 2;
              break;
        case UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION:
                // 38.321 Ch6.1.3.7
                break;
136 137 138

        case UL_SCH_LCID_S_BSR:
        case UL_SCH_LCID_S_TRUNCATED_BSR:
139 140 141 142
               //38.321 section 6.1.3.1
               //fixed length
               mac_ce_len =1;
               /* Extract short BSR value */
ChiehChun's avatar
ChiehChun committed
143 144
               ce_ptr = &pdu_ptr[mac_subheader_len];
               NR_BSR_SHORT *bsr_s = (NR_BSR_SHORT *) ce_ptr;
145 146
               sched_ctrl->estimated_ul_buffer = 0;
               sched_ctrl->estimated_ul_buffer = NR_SHORT_BSR_TABLE[bsr_s->Buffer_size];
147
               LOG_D(NR_MAC, "SHORT BSR, LCG ID %d, BS Index %d, BS value < %d, est buf %d\n",
148 149 150 151
                     bsr_s->LcgID,
                     bsr_s->Buffer_size,
                     NR_SHORT_BSR_TABLE[bsr_s->Buffer_size],
                     sched_ctrl->estimated_ul_buffer);
152 153 154
        	break;

        case UL_SCH_LCID_L_BSR:
155
        case UL_SCH_LCID_L_TRUNCATED_BSR:
156 157 158 159 160 161 162 163 164
        	//38.321 section 6.1.3.1
        	//variable length
        	mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L;
        	mac_subheader_len = 2;
        	if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){
        		mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8;
        		mac_subheader_len = 3;
        	}
        	/* Extract long BSR value */
ChiehChun's avatar
ChiehChun committed
165 166
               ce_ptr = &pdu_ptr[mac_subheader_len];
               NR_BSR_LONG *bsr_l = (NR_BSR_LONG *) ce_ptr;
167
               sched_ctrl->estimated_ul_buffer = 0;
168

169 170
               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;
171

172
               LOG_D(NR_MAC, "LONG BSR, LCG ID(7-0) %d/%d/%d/%d/%d/%d/%d/%d\n",
173 174 175 176
                     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++){
177
                 LOG_D(NR_MAC, "LONG BSR, %d/%d (n/n_Lcg), BS Index %d, BS value < %d",
178 179
                       n, n_Lcg, pdu_ptr[mac_subheader_len + 1 + n],
                       NR_LONG_BSR_TABLE[pdu_ptr[mac_subheader_len + 1 + n]]);
180 181
                 sched_ctrl->estimated_ul_buffer +=
                       NR_LONG_BSR_TABLE[pdu_ptr[mac_subheader_len + 1 + n]];
182 183
               }

184
               break;
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228

        case UL_SCH_LCID_C_RNTI:
        	//38.321 section 6.1.3.2
        	//fixed length
        	mac_ce_len = 2;
        	/* Extract CRNTI value */
        	break;

        case UL_SCH_LCID_SINGLE_ENTRY_PHR:
        	//38.321 section 6.1.3.8
        	//fixed length
        	mac_ce_len = 2;
        	/* Extract SINGLE ENTRY PHR elements for PHR calculation */
        	break;

        case UL_SCH_LCID_MULTI_ENTRY_PHR_1_OCT:
        	//38.321 section 6.1.3.9
        	//  varialbe length
        	mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L;
        	mac_subheader_len = 2;
        	if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){
        		mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8;
        		mac_subheader_len = 3;
        	}
        	/* 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
        	mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L;
        	mac_subheader_len = 2;
        	if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){
        		mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8;
        		mac_subheader_len = 3;
        	}
        	/* 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;

229 230 231 232 233 234 235 236 237 238
        case UL_SCH_LCID_SRB1:
          if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){
            //mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8;
            mac_subheader_len = 3;
            mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L1 & 0x7f) << 8)
                | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L2 & 0xff);
          } else {
            mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L;
            mac_subheader_len = 2;
          }
239
          LOG_D(NR_MAC, "[UE %d] Frame %d : ULSCH -> UL-DCCH %d (gNB %d, %d bytes), rnti: %d \n", module_idP, frameP, rx_lcid, module_idP, mac_sdu_len, rnti);
240 241 242 243 244 245 246 247 248 249 250 251
          mac_rlc_data_ind(module_idP,
              rnti,
              module_idP,
              frameP,
              ENB_FLAG_YES,
              MBMS_FLAG_NO,
              rx_lcid,
              (char *) (pdu_ptr + mac_subheader_len),
              mac_sdu_len,
              1,
              NULL);
          break;
252
       case UL_SCH_LCID_SRB2:
253 254 255 256 257
              // todo
              break;
        case UL_SCH_LCID_SRB3:
              // todo
              break;
258

259
        case UL_SCH_LCID_CCCH:
260
        case UL_SCH_LCID_CCCH1:
261
          // fixed length
262
          mac_subheader_len = 1;
263 264 265 266 267

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

rmagueta's avatar
rmagueta committed
268
            // Check if it is a valid CCCH1 message, we get all 00's messages very often
269 270 271 272 273 274 275
            int i = 0;
            for(i=0; i<(mac_subheader_len+mac_sdu_len); i++) {
              if(pdu_ptr[i] != 0) {
                break;
              }
            }
            if (i == (mac_subheader_len+mac_sdu_len)) {
rmagueta's avatar
rmagueta committed
276
              LOG_D(NR_MAC, "%s() Invalid CCCH1 message!, pdu_len: %d\n", __func__, pdu_len);
277 278
              done = 1;
              break;
279 280 281 282 283 284
            }
          } else {
            // fixed length of 6 bytes
            mac_sdu_len = 6;
          }

285 286 287 288 289 290 291 292
          nr_mac_rrc_data_ind(module_idP,
                              CC_id,
                              frameP,
                              0,
                              0,
                              rnti,
                              CCCH,
                              pdu_ptr+mac_subheader_len,
293
                              mac_sdu_len,
294 295
                              0);
          break;
296

297 298 299 300 301 302 303 304 305 306 307 308 309
        case UL_SCH_LCID_DTCH:
                //  check if LCID is valid at current time.
                if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){
                    //mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8;
                    mac_subheader_len = 3;
                    mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L1 & 0x7f) << 8)
                    | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L2 & 0xff);

                } else {
                  mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L;
                  mac_subheader_len = 2;
                }

310
                LOG_D(NR_MAC, "[UE %d] Frame %d : ULSCH -> UL-DTCH %d (gNB %d, %d bytes)\n", module_idP, frameP, rx_lcid, module_idP, mac_sdu_len);
311
		int UE_id = find_nr_UE_id(module_idP, rnti);
312
		RC.nrmac[module_idP]->UE_info.mac_stats[UE_id].lc_bytes_rx[rx_lcid] += mac_sdu_len;
313
                #if defined(ENABLE_MAC_PAYLOAD_DEBUG)
314
		    log_dump(NR_MAC, pdu_ptr + mac_subheader_len, 32, LOG_DUMP_CHAR, "\n");
315 316 317

                #endif

cig's avatar
cig committed
318 319 320 321 322 323 324 325 326 327 328
                mac_rlc_data_ind(module_idP,
                                 rnti,
                                 module_idP,
                                 frameP,
                                 ENB_FLAG_YES,
                                 MBMS_FLAG_NO,
                                 rx_lcid,
                                 (char *) (pdu_ptr + mac_subheader_len),
                                 mac_sdu_len,
                                 1,
                                 NULL);
329

330 331 332 333 334 335
                /* Updated estimated buffer when receiving data */
                if (sched_ctrl->estimated_ul_buffer >= mac_sdu_len)
                  sched_ctrl->estimated_ul_buffer -= mac_sdu_len;
                else
                  sched_ctrl->estimated_ul_buffer = 0;

336 337 338
            break;

        default:
339
          LOG_D(NR_MAC, "Received unknown MAC header (LCID = 0x%02x)\n", rx_lcid);
340 341
          return;
          break;
cig's avatar
cig committed
342 343 344 345
        }
        pdu_ptr += ( mac_subheader_len + mac_ce_len + mac_sdu_len );
        pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len );

346
        if (pdu_len < 0) {
347 348
          LOG_E(NR_MAC, "%s() residual mac pdu length < 0!, pdu_len: %d\n", __func__, pdu_len);
          LOG_E(NR_MAC, "MAC PDU ");
349 350 351
          for (int i = 0; i < 20; i++) // Only printf 1st - 20nd bytes
            printf("%02x ", pdu_ptr[i]);
          printf("\n");
352 353
          return;
        }
354 355
    }
}
356

357 358 359 360 361 362 363
void handle_nr_ul_harq(module_id_t mod_id,
                       frame_t frame,
                       sub_frame_t slot,
                       const nfapi_nr_crc_t *crc_pdu)
{
  int UE_id = find_nr_UE_id(mod_id, crc_pdu->rnti);
  if (UE_id < 0) {
364
    LOG_E(NR_MAC, "%s(): unknown RNTI %04x in PUSCH\n", __func__, crc_pdu->rnti);
365 366 367 368
    return;
  }
  NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
  NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
369

370 371
  int8_t harq_pid = sched_ctrl->feedback_ul_harq.head;
  while (crc_pdu->harq_id != harq_pid || harq_pid < 0) {
372
    LOG_W(NR_MAC,
373 374 375
          "Unexpected ULSCH HARQ PID %d (have %d) for RNTI %04x (ignore this warning for RA)\n",
          crc_pdu->harq_id,
          harq_pid,
376
          crc_pdu->rnti);
377 378 379 380
    if (harq_pid < 0)
      return;

    remove_front_nr_list(&sched_ctrl->feedback_ul_harq);
381 382 383 384 385 386 387 388 389 390
    sched_ctrl->ul_harq_processes[harq_pid].is_waiting = false;
    if(sched_ctrl->ul_harq_processes[harq_pid].round == MAX_HARQ_ROUNDS) {
      sched_ctrl->ul_harq_processes[harq_pid].ndi ^= 1;
      sched_ctrl->ul_harq_processes[harq_pid].round = 0;
      UE_info->mac_stats[UE_id].ulsch_errors++;
      add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid);
    } else {
      sched_ctrl->ul_harq_processes[harq_pid].round++;
      add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid);
    }
391
    harq_pid = sched_ctrl->feedback_ul_harq.head;
392 393 394 395 396 397 398 399 400
  }
  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;
401
    LOG_D(NR_MAC,
402 403 404 405 406 407 408
          "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);
  } else if (harq->round == MAX_HARQ_ROUNDS) {
    harq->ndi ^= 1;
    harq->round = 0;
409
    LOG_D(NR_MAC,
410 411 412 413 414 415 416
          "RNTI %04x: Ulharq id %d crc failed in all rounds\n",
          crc_pdu->rnti,
          harq_pid);
    UE_info->mac_stats[UE_id].ulsch_errors++;
    add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid);
  } else {
    harq->round++;
417
    LOG_D(NR_MAC,
418 419
          "Ulharq id %d crc failed for RNTI %04x\n",
          harq_pid,
420
          crc_pdu->rnti);
421 422
    add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid);
  }
423 424
}

425 426 427
/*
* When data are received on PHY and transmitted to MAC
*/
428 429 430
void nr_rx_sdu(const module_id_t gnb_mod_idP,
               const int CC_idP,
               const frame_t frameP,
431
               const sub_frame_t slotP,
432 433 434 435
               const rnti_t rntiP,
               uint8_t *sduP,
               const uint16_t sdu_lenP,
               const uint16_t timing_advance,
436 437
               const uint8_t ul_cqi,
               const uint16_t rssi){
Robert Schmidt's avatar
Robert Schmidt committed
438 439 440 441 442 443
  gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP];
  NR_UE_info_t *UE_info = &gNB_mac->UE_info;

  const int current_rnti = rntiP;
  const int UE_id = find_nr_UE_id(gnb_mod_idP, current_rnti);
  const int target_snrx10 = gNB_mac->pusch_target_snrx10;
444

445
  if (UE_id != -1) {
Robert Schmidt's avatar
Robert Schmidt committed
446 447 448 449 450 451 452
    NR_UE_sched_ctrl_t *UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id];
    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));
453

454
    UE_info->mac_stats[UE_id].ulsch_total_bytes_rx += sdu_lenP;
455
    LOG_D(NR_MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d TA %d sduP %p\n",
456 457 458 459
          gnb_mod_idP,
          harq_pid,
          CC_idP,
          frameP,
460
          slotP,
461 462
          current_rnti,
          UE_id,
463
          ul_cqi,
464
          timing_advance,
465
          sduP);
466

467 468 469
    // if not missed detection (10dB threshold for now)
    if (UE_scheduling_control->ul_rssi < (100+rssi)) {
      UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10,ul_cqi,30);
470 471
      if (timing_advance != 0xffff)
        UE_scheduling_control->ta_update = timing_advance;
Francesco Mani's avatar
Francesco Mani committed
472
      UE_scheduling_control->ul_rssi = rssi;
rmagueta's avatar
rmagueta committed
473
      LOG_D(NR_MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update);
474 475 476 477 478
    }
    else{
      UE_scheduling_control->tpc0 = 1;
    }

479
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
Laurent's avatar
Laurent committed
480

481
    LOG_I(NR_MAC, "Printing received UL MAC payload at gNB side: %d \n");
482
    for (int i = 0; i < sdu_lenP ; i++) {
483 484 485
	  //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]);
486 487
    }
    printf("\n");
Laurent's avatar
Laurent committed
488

489 490 491
#endif

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

494 495
      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;
496 497 498
      if (UE_scheduling_control->sched_ul_bytes < 0)
        UE_scheduling_control->sched_ul_bytes = 0;

499
      nr_process_mac_pdu(gnb_mod_idP, current_rnti, CC_idP, frameP, sduP, sdu_lenP);
cig's avatar
cig committed
500
    }
501
    else {
502 503 504
      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){
505 506
        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;
507 508 509
        if (UE_scheduling_control->sched_ul_bytes < 0)
          UE_scheduling_control->sched_ul_bytes = 0;
      }
510
    }
511 512 513 514 515 516 517 518 519 520 521 522 523
  } 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");
    }
524

Robert Schmidt's avatar
Robert Schmidt committed
525 526 527 528
    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));

529 530 531 532 533 534 535 536
    /* 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;

537 538
      if(no_sig) {
        LOG_W(NR_MAC, "Random Access %i failed at state %i\n", i, ra->state);
539
        nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti);
540
        nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
541 542 543 544 545
      } else {

        // random access pusch with TC-RNTI
        if (ra->rnti != current_rnti) {
          LOG_W(NR_MAC,
rmagueta's avatar
rmagueta committed
546
                "expected TC_RNTI %04x to match current RNTI %04x\n",
547 548
                ra->rnti,
                current_rnti);
rmagueta's avatar
rmagueta committed
549 550 551 552 553 554 555

          if( (frameP==ra->Msg3_frame) && (slotP==ra->Msg3_slot) ) {
            LOG_W(NR_MAC, "Random Access %i failed at state %i\n", i, ra->state);
            nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti);
            nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
          }

556 557
          continue;
        }
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
	int UE_id=-1;
	
	UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti, ra->CellGroup);
	UE_info->UE_beam_index[UE_id] = ra->beam_id;
	
	// re-initialize ta update variables after RA procedure completion
	UE_info->UE_sched_ctrl[UE_id].ta_frame = frameP;
	
	LOG_I(NR_MAC,
	      "reset RA state information for RA-RNTI %04x/index %d\n",
	      ra->rnti,
	      i);
	  
	LOG_I(NR_MAC,
	      "[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, "
	      "adding UE MAC Context UE_id %d/RNTI %04x\n",
	      gnb_mod_idP,
	      current_rnti,
	      UE_id,
	      ra->rnti);
	  
	if(ra->cfra) {
	  
	  LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) CFRA procedure succeeded!\n", UE_id, ra->rnti);
	  nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti);
	  nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
	  UE_info->active[UE_id] = true;
	  
	} else {
	  
	  LOG_I(NR_MAC,"[RAPROC] RA-Msg3 received (sdu_lenP %d)\n",sdu_lenP);
	  LOG_D(NR_MAC,"[RAPROC] Received Msg3:\n");
590
          for (int k = 0; k < sdu_lenP; k++) {
rmagueta's avatar
rmagueta committed
591
            LOG_D(NR_MAC,"(%i): 0x%x\n",k,sduP[k]);
592
          }
593
	  
594 595 596 597
          // 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);
598

599
          nr_process_mac_pdu(gnb_mod_idP, current_rnti, CC_idP, frameP, sduP, sdu_lenP);
600

601 602 603
          ra->state = Msg4;
          ra->Msg4_frame = ( frameP +2 ) % 1024;
          ra->Msg4_slot = 1;
rmagueta's avatar
rmagueta committed
604
          LOG_I(NR_MAC, "Scheduling RA-Msg4 for TC_RNTI %04x (state %d, frame %d, slot %d)\n", ra->rnti, ra->state, ra->Msg4_frame, ra->Msg4_slot);
605 606

        }
607 608
        return;

609
      }
610 611 612 613 614 615
    }
  } 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;
616

617
      LOG_W(NR_MAC, "Random Access %i failed at state %i\n", i, ra->state);
618
      nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti);
619
      nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
620
    }
621
  }
622 623
}

624 625 626 627 628
long get_K2(NR_ServingCellConfigCommon_t *scc,NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu) {
  DevAssert(scc);
  const NR_PUSCH_TimeDomainResourceAllocation_t *tda_list = ubwp ?
    ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]:
    scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment];
629 630 631 632 633 634 635 636 637 638
  if (tda_list->k2)
    return *tda_list->k2;
  else if (mu < 2)
    return 1;
  else if (mu == 2)
    return 2;
  else
    return 3;
}

639 640 641 642 643 644 645
int next_list_entry_looped(NR_list_t *list, int UE_id)
{
  if (UE_id < 0)
    return list->head;
  return list->next[UE_id] < 0 ? list->head : list->next[UE_id];
}

646
float ul_thr_ue[MAX_MOBILES_PER_GNB];
647
int bsr0ue = -1;
ChiehChun's avatar
ChiehChun committed
648 649 650 651 652 653 654 655 656 657 658 659 660 661
void pf_ul(module_id_t module_id,
           frame_t frame,
           sub_frame_t slot,
           int num_slots_per_tdd,
           NR_list_t *UE_list,
           int n_rb_sched,
           uint8_t *rballoc_mask,
           int max_num_ue) {

  const int CC_id = 0;
  const int tda = 1;
  NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[CC_id].ServingCellConfigCommon;
  NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
  const int min_rb = 5;
Robert Schmidt's avatar
Robert Schmidt committed
662
  float coeff_ue[MAX_MOBILES_PER_GNB];
663 664 665
  // UEs that could be scheduled
  int ue_array[MAX_MOBILES_PER_GNB];
  NR_list_t UE_sched = { .head = -1, .next = ue_array, .tail = -1, .len = MAX_MOBILES_PER_GNB };
ChiehChun's avatar
ChiehChun committed
666

667 668 669 670 671 672
  /* Hack: currently, we do not have SR, and need to schedule UEs continuously.
   * To keep the wasted resources low, we switch UEs to be scheduled in a
   * round-robin fashion below, and only schedule a UE with BSR=0 if it is the
   * selected one */
  bsr0ue = next_list_entry_looped(UE_list, bsr0ue);

ChiehChun's avatar
ChiehChun committed
673 674
  /* Loop UE_list to calculate throughput and coeff */
  for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
675 676 677

    if (UE_info->Msg4_ACKed[UE_id] != true) continue;

ChiehChun's avatar
ChiehChun committed
678
    NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
679
    int rbStart = 0; /*NRRIV2PRBOFFSET(sched_ctrl->active_bwp ?
680 681
				  sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth:
				  scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 
682
				  MAX_BWP_SIZE);*/
683 684 685 686
    const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp?
				      sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth:
				      scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 
				      MAX_BWP_SIZE);
ChiehChun's avatar
ChiehChun committed
687 688

    /* Calculate throughput */
689 690 691
    const float a = 0.0005f; // corresponds to 200ms window
    const uint32_t b = UE_info->mac_stats[UE_id].ulsch_current_bytes;
    ul_thr_ue[UE_id] = (1 - a) * ul_thr_ue[UE_id] + a * b;
ChiehChun's avatar
ChiehChun committed
692 693

    /* Save PUSCH field */
Robert Schmidt's avatar
Robert Schmidt committed
694 695 696
    /* we want to avoid a lengthy deduction of DMRS and other parameters in
     * every TTI if we can save it, so check whether dci_format, TDA, or
     * num_dmrs_cdm_grps_no_data has changed and only then recompute */
ChiehChun's avatar
ChiehChun committed
697
    sched_ctrl->sched_pusch.time_domain_allocation = tda;
698 699 700 701 702 703 704 705
    NR_BWP_DownlinkDedicated_t *bwp_Dedicated=NULL;
    if (sched_ctrl->active_bwp) bwp_Dedicated = sched_ctrl->active_bwp->bwp_Dedicated;
    else if (UE_info->CellGroup[UE_id] &&
	     UE_info->CellGroup[UE_id]->spCellConfig &&
	     UE_info->CellGroup[UE_id]->spCellConfig->spCellConfigDedicated) 
	bwp_Dedicated = UE_info->CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->initialDownlinkBWP;
    sched_ctrl->search_space = get_searchspace(scc,bwp_Dedicated, 
					       bwp_Dedicated ? 
706 707 708 709
					       NR_SearchSpace__searchSpaceType_PR_ue_Specific:
					       NR_SearchSpace__searchSpaceType_PR_common);
    sched_ctrl->coreset = get_coreset(scc,sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
    if (sched_ctrl->coreset == NULL) sched_ctrl->coreset = RC.nrmac[module_id]->sched_ctrlCommon->coreset;
ChiehChun's avatar
ChiehChun committed
710
    const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats;
711 712
    const int dci_format = sched_ctrl->active_bwp ? (f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0) : NR_UL_DCI_FORMAT_0_0;
    const uint8_t num_dmrs_cdm_grps_no_data = sched_ctrl->active_bwp ? 1 : 2;
ChiehChun's avatar
ChiehChun committed
713 714 715 716
    NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save;
    if (ps->time_domain_allocation != tda
        || ps->dci_format != dci_format
        || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data)
Robert Schmidt's avatar
Robert Schmidt committed
717
      nr_save_pusch_fields(scc, sched_ctrl->active_ubwp, dci_format, tda, num_dmrs_cdm_grps_no_data, ps);
ChiehChun's avatar
ChiehChun committed
718

719 720 721 722
    /* Check if retransmission is necessary */
    sched_ctrl->sched_pusch.ul_harq_pid = sched_ctrl->retrans_ul_harq.head;
    if (sched_ctrl->sched_pusch.ul_harq_pid >= 0) {
      /* RETRANSMISSION: Allocate retransmission*/
723 724 725
      /* Find free CCE */
      bool freeCCE = find_free_CCE(module_id, slot, UE_id);
      if (!freeCCE) {
726
        LOG_D(NR_MAC, "%4d.%2d no free CCE for retransmission UL DCI UE %04x\n", frame, slot, UE_info->rnti[UE_id]);
727 728 729 730 731 732 733
        continue;
      }
      /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
      max_num_ue--;
      if (max_num_ue < 0)
        return;

734 735 736 737 738 739 740
      /* Save shced_frame and sched_slot before overwrite by previous PUSCH filed */
      NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[sched_ctrl->sched_pusch.ul_harq_pid];
      cur_harq->sched_pusch.frame = sched_ctrl->sched_pusch.frame;
      cur_harq->sched_pusch.slot = sched_ctrl->sched_pusch.slot;
      /* Get previous PSUCH filed info */
      sched_ctrl->sched_pusch = cur_harq->sched_pusch;
      NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
741
      LOG_D(NR_MAC, "%4d.%2d Allocate UL retransmission UE %d/RNTI %04x sched %4d.%2d (%d RBs)\n",
742 743 744 745 746 747
            frame, slot, UE_id, UE_info->rnti[UE_id],
            sched_pusch->frame, sched_pusch->slot,
            sched_pusch->rbSize);

      while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
      if (rbStart + sched_pusch->rbSize >= bwpSize) {
748
        LOG_W(NR_MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources (rbStart %d, sched_pusch->rbSize %d, bwpSize %d)\n",
749
              UE_id, UE_info->rnti[UE_id],rbStart,sched_pusch->rbSize,bwpSize);
750 751 752 753 754 755 756 757 758 759 760 761 762
        return;
      }
      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++)
        rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0;

      continue;
    }

Robert Schmidt's avatar
Robert Schmidt committed
763
    /* Calculate TBS from MCS */
ChiehChun's avatar
ChiehChun committed
764
    NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
Robert Schmidt's avatar
Robert Schmidt committed
765
    const int mcs = 9;
ChiehChun's avatar
ChiehChun committed
766 767 768 769 770 771 772 773 774
    sched_pusch->mcs = mcs;
    sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table);
    sched_pusch->Qm = nr_get_Qm_ul(mcs, ps->mcs_table);
    if (ps->pusch_Config->tp_pi2BPSK
        && ((ps->mcs_table == 3 && mcs < 2) || (ps->mcs_table == 4 && mcs < 6))) {
      sched_pusch->R >>= 1;
      sched_pusch->Qm <<= 1;
    }

775 776
    /* Check BSR and schedule UE if it is zero to avoid starvation, since we do
     * not have SR (yet) */
777
    if (sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes <= 0) {
778 779
      if (UE_id != bsr0ue)
        continue;
780
      /* if no data, pre-allocate 5RB */
781 782
      bool freeCCE = find_free_CCE(module_id, slot, UE_id);
      if (!freeCCE) {
783
        LOG_I(NR_MAC, "%4d.%2d no free CCE for UL DCI UE %04x (BSR 0)\n", frame, slot, UE_info->rnti[UE_id]);
784 785 786 787 788 789 790
        continue;
      }
      /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
      max_num_ue--;
      if (max_num_ue < 0)
        return;

791
      LOG_D(NR_MAC,"Looking for min_rb %d RBs, starting at %d\n", min_rb,rbStart);
792 793
      while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
      if (rbStart + min_rb >= bwpSize) {
794
        LOG_W(NR_MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources (rbStart %d, min_rb %d, bwpSize %d\n",
795
              UE_id, UE_info->rnti[UE_id],rbStart,min_rb,bwpSize);
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
        return;
      }
      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,
                                            1 /* NrOfLayers */)
                             >> 3;

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

      continue;
816
    }
817 818 819

    /* Create UE_sched for UEs eligibale for new data transmission*/
    add_tail_nr_list(&UE_sched, UE_id);
Robert Schmidt's avatar
Robert Schmidt committed
820 821

    /* Calculate coefficient*/
822 823 824 825 826 827 828 829 830
    const uint32_t tbs = nr_compute_tbs(sched_pusch->Qm,
                                        sched_pusch->R,
                                        1, // rbSize
                                        ps->nrOfSymbols,
                                        ps->N_PRB_DMRS * ps->num_dmrs_symb,
                                        0, // nb_rb_oh
                                        0,
                                        1 /* NrOfLayers */)
                          >> 3;
Robert Schmidt's avatar
Robert Schmidt committed
831
    coeff_ue[UE_id] = (float) tbs / ul_thr_ue[UE_id];
832
    LOG_D(NR_MAC,"b %d, ul_thr_ue[%d] %f, tbs %d, coeff_ue[%d] %f\n",
Robert Schmidt's avatar
Robert Schmidt committed
833
          b, UE_id, ul_thr_ue[UE_id], tbs, UE_id, coeff_ue[UE_id]);
834 835
  }

Robert Schmidt's avatar
Robert Schmidt committed
836 837

  /* Loop UE_sched to find max coeff and allocate transmission */
838
  while (UE_sched.head >= 0 && max_num_ue> 0 && n_rb_sched > 0) {
Robert Schmidt's avatar
Robert Schmidt committed
839
    /* Find max coeff */
840 841 842 843 844 845 846 847 848 849 850 851 852 853 854
    int *max = &UE_sched.head; /* Find max coeff: assume head is max */
    int *p = &UE_sched.next[*max];
    while (*p >= 0) {
      /* Find max coeff: if the current one has larger coeff, save for later */
      if (coeff_ue[*p] > coeff_ue[*max])
        max = p;
      p = &UE_sched.next[*p];
    }
    /* Find max coeff: remove the max one: do not use remove_nr_list() since it
     * goes through the whole list every time. Note that UE_sched.tail might
     * not be set correctly anymore */
    const int UE_id = *max;
    p = &UE_sched.next[*max];
    *max = UE_sched.next[*max];
    *p = -1;
Robert Schmidt's avatar
Robert Schmidt committed
855

856 857
    bool freeCCE = find_free_CCE(module_id, slot, UE_id);
    if (!freeCCE) {
858
      LOG_D(NR_MAC, "%4d.%2d no free CCE for UL DCI UE %04x\n", frame, slot, UE_info->rnti[UE_id]);
859 860 861 862
      continue;
    }

    /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
Robert Schmidt's avatar
Robert Schmidt committed
863
    max_num_ue--;
864 865
    if (max_num_ue < 0)
      return;
Robert Schmidt's avatar
Robert Schmidt committed
866

867
    NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
868 869 870
    NR_BWP_t *genericParameters = sched_ctrl->active_ubwp ? &sched_ctrl->active_ubwp->bwp_Common->genericParameters:&scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;  
    int rbStart = 0; /*NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);*/
    const uint16_t bwpSize = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
Robert Schmidt's avatar
Robert Schmidt committed
871 872
    NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;

ChiehChun's avatar
ChiehChun committed
873 874 875 876

    while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
    sched_pusch->rbStart = rbStart;
    if (rbStart + min_rb >= bwpSize) {
877
      LOG_W(NR_MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources (rbStart %d, min_rb %d, bwpSize %d\n",
878
	    UE_id, UE_info->rnti[UE_id],rbStart,min_rb,bwpSize);
ChiehChun's avatar
ChiehChun committed
879
      return;
880
    }
ChiehChun's avatar
ChiehChun committed
881 882 883 884 885 886 887 888 889 890

    /* Calculate the current scheduling bytes */
    const int B = cmax(sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, 0);
    uint16_t rbSize = min_rb - 1;
    do {
      rbSize++;
      sched_pusch->rbSize = rbSize;
      sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm,
                                            sched_pusch->R,
                                            sched_pusch->rbSize,
Robert Schmidt's avatar
Robert Schmidt committed
891 892
                                            sched_ctrl->pusch_save.nrOfSymbols,
                                            sched_ctrl->pusch_save.N_PRB_DMRS * sched_ctrl->pusch_save.num_dmrs_symb,
ChiehChun's avatar
ChiehChun committed
893 894 895 896 897 898
                                            0, // nb_rb_oh
                                            0,
                                            1 /* NrOfLayers */)
                             >> 3;
    } while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart+rbSize] &&
             sched_pusch->tb_size < B);
899
    LOG_D(NR_MAC,"rbSize %d, TBS %d, est buf %d, sched_ul %d, B %d\n",
ChiehChun's avatar
ChiehChun committed
900 901 902
          rbSize, sched_pusch->tb_size, sched_ctrl->estimated_ul_buffer, sched_ctrl->sched_ul_bytes, B);

    /* Mark the corresponding RBs as used */
903
    n_rb_sched -= sched_pusch->rbSize;
ChiehChun's avatar
ChiehChun committed
904 905
    for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
      rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0;
906 907 908
  }
}

909
bool nr_simple_ulsch_preprocessor(module_id_t module_id,
910
                                  frame_t frame,
911 912 913 914 915 916 917 918
                                  sub_frame_t slot,
                                  int num_slots_per_tdd,
                                  uint64_t ulsch_in_slot_bitmap) {
  gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
  NR_COMMON_channels_t *cc = nr_mac->common_channels;
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
  const int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing;
  NR_UE_info_t *UE_info = &nr_mac->UE_info;
919 920

  if (UE_info->num_UEs == 0)
921
    return false;
922 923 924

  const int CC_id = 0;

ChiehChun's avatar
ChiehChun committed
925
  /* NOT support different K2 in here, Get the K2 for first UE */
ChiehChun's avatar
ChiehChun committed
926 927
  int UE_id = UE_info->list.head;
  NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
928 929
  const int tda = 1;
  const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList =
930 931 932 933
    sched_ctrl->active_ubwp ?
    sched_ctrl->active_ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList:
    scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;

934 935 936 937
  AssertFatal(tda < tdaList->list.count,
              "time domain assignment %d >= %d\n",
              tda,
              tdaList->list.count);
ChiehChun's avatar
ChiehChun committed
938

939
  int K2 = get_K2(scc,sched_ctrl->active_ubwp, tda, mu);
ChiehChun's avatar
ChiehChun committed
940 941
  const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]);
  const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
942
  if (!is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot))
943
    return false;
944

945 946
  sched_ctrl->sched_pusch.slot = sched_slot;
  sched_ctrl->sched_pusch.frame = sched_frame;
947

ChiehChun's avatar
ChiehChun committed
948
  /* Confirm all the UE have same K2 as the first UE */
ChiehChun's avatar
ChiehChun committed
949
  for (UE_id = UE_info->list.next[UE_id]; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
ChiehChun's avatar
ChiehChun committed
950
    NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
951 952
    AssertFatal(K2 == get_K2(scc,sched_ctrl->active_ubwp, tda, mu),
                "Different K2, %d(UE%d) != %ld(UE%d)\n", K2, 0, get_K2(scc,sched_ctrl->active_ubwp, tda, mu), UE_id);
ChiehChun's avatar
ChiehChun committed
953 954
    sched_ctrl->sched_pusch.slot = sched_slot;
    sched_ctrl->sched_pusch.frame = sched_frame;
955
  }
Robert Schmidt's avatar
Robert Schmidt committed
956

957
  /* Change vrb_map_UL to rballoc_mask */
958 959
  uint16_t *vrb_map_UL =
      &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * MAX_BWP_SIZE];
960 961 962 963
  const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp ? 
				    sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth:
				    scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 
				    MAX_BWP_SIZE);
964

965
  int st = 0, e = 0, len = 0;
966
  for (int i = 0; i < bwpSize; i++) {
967
    while (vrb_map_UL[i] == 1 && i<bwpSize)
968 969
      i++;
    st = i;
970
    while (vrb_map_UL[i] == 0 && i<bwpSize)
971 972 973 974 975
      i++;
    if (i - st > len) {
      len = i - st;
      e = i - 1;
    }
976
  }
977 978 979 980 981 982 983
  st = e - len + 1;

  uint8_t rballoc_mask[bwpSize];

  /* 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++)
    rballoc_mask[i] = i >= st && i <= e;
984

ChiehChun's avatar
ChiehChun committed
985 986 987 988 989 990
  /* proportional fair scheduling algorithm */
  pf_ul(module_id,
        frame,
        slot,
        num_slots_per_tdd,
        &UE_info->list,
991
        len,
ChiehChun's avatar
ChiehChun committed
992 993
        rballoc_mask,
        2);
994
  return true;
995 996
}

997 998 999 1000 1001 1002
void nr_schedule_ulsch(module_id_t module_id,
                       frame_t frame,
                       sub_frame_t slot,
                       int num_slots_per_tdd,
                       int ul_slots,
                       uint64_t ulsch_in_slot_bitmap) {
1003 1004 1005
  /* 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 */
  if (is_xlsch_in_slot(ulsch_in_slot_bitmap, slot)) {
1006
    LOG_D(NR_MAC, "Current slot %d is NOT DL slot, cannot schedule DCI0 for UL data\n", slot);
1007 1008
    return;
  }
1009
  bool do_sched = RC.nrmac[module_id]->pre_processor_ul(
1010
      module_id, frame, slot, num_slots_per_tdd, ulsch_in_slot_bitmap);
1011 1012
  if (!do_sched)
    return;
1013

1014 1015 1016 1017 1018 1019 1020
  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 */
1021
  nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_bwp_coreset[MAX_NUM_BWP][MAX_NUM_CORESET] = {{0}};
1022

1023
  NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon;
1024
  NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
1025
  const NR_list_t *UE_list = &UE_info->list;
1026 1027
  for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
    NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
1028
    UE_info->mac_stats[UE_id].ulsch_current_bytes = 0;
1029 1030
    /* 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
1031
    NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
1032
    LOG_D(NR_MAC,"UE %x : sched_pusch->rbSize %d\n",UE_info->rnti[UE_id],sched_pusch->rbSize);
Robert Schmidt's avatar
Robert Schmidt committed
1033
    if (sched_pusch->rbSize <= 0)
1034 1035 1036 1037
      continue;

    uint16_t rnti = UE_info->rnti[UE_id];

1038 1039 1040 1041 1042 1043 1044 1045
    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,
                  "no free HARQ process available for UE %d\n",
                  UE_id);
      remove_front_nr_list(&sched_ctrl->available_ul_harq);
1046
      sched_pusch->ul_harq_pid = harq_id;
1047 1048 1049 1050 1051 1052 1053 1054 1055
    } 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
1056
    NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[harq_id];
1057 1058 1059 1060
    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
1061

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

1064 1065 1066 1067
    /* pre-computed PUSCH values that only change if time domain allocation,
     * DCI format, or DMRS parameters change. Updated in the preprocessor
     * through nr_save_pusch_fields() */
    NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save;
1068

1069 1070
    /* Statistics */
    UE_info->mac_stats[UE_id].ulsch_rounds[cur_harq->round]++;
1071
    if (cur_harq->round == 0) {
1072
      UE_info->mac_stats[UE_id].ulsch_total_bytes_scheduled += sched_pusch->tb_size;
1073 1074 1075
      /* 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;
1076
      sched_ctrl->sched_ul_bytes += sched_pusch->tb_size;
1077
    } else {
1078
      LOG_D(NR_MAC,
1079
            "%d.%2d UL retransmission RNTI %04x sched %d.%2d HARQ PID %d round %d NDI %d\n",
1080 1081 1082 1083 1084
            frame,
            slot,
            rnti,
            sched_pusch->frame,
            sched_pusch->slot,
1085 1086 1087
            harq_id,
            cur_harq->round,
            cur_harq->ndi);
1088
    }
1089
    UE_info->mac_stats[UE_id].ulsch_current_bytes = sched_pusch->tb_size;
1090

1091
    LOG_D(NR_MAC,
1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
          "%4d.%2d RNTI %04x UL sched %4d.%2d start %d RBS %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n",
          frame,
          slot,
          rnti,
          sched_pusch->frame,
          sched_pusch->slot,
          sched_pusch->rbStart,
          sched_pusch->rbSize,
          sched_pusch->mcs,
          sched_pusch->tb_size,
          harq_id,
          cur_harq->round,
          cur_harq->ndi);
1105

1106
    /* PUSCH in a later slot, but corresponding DCI now! */
Robert Schmidt's avatar
Robert Schmidt committed
1107 1108 1109
    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,
1110 1111 1112 1113
                "%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
1114 1115
                sched_pusch->frame,
                sched_pusch->slot);
1116 1117 1118 1119 1120 1121
    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;

1122
    LOG_D(NR_MAC, "%4d.%2d Scheduling UE specific PUSCH for sched %d.%d, ul_tto_req %d.%d\n", frame, slot,
1123
    sched_pusch->frame,sched_pusch->slot,future_ul_tti_req->SFN,future_ul_tti_req->Slot);
1124 1125 1126 1127 1128

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

1129
    /* FAPI: BWP */
1130 1131 1132 1133
    NR_BWP_t *genericParameters = sched_ctrl->active_ubwp ? &sched_ctrl->active_ubwp->bwp_Common->genericParameters:&scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;  
    pusch_pdu->bwp_size  = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
    pusch_pdu->bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
    pusch_pdu->subcarrier_spacing = genericParameters->subcarrierSpacing;
1134 1135
    pusch_pdu->cyclic_prefix = 0;

1136
    /* FAPI: PUSCH information always included */
1137 1138 1139
    pusch_pdu->target_code_rate = sched_pusch->R;
    pusch_pdu->qam_mod_order = sched_pusch->Qm;
    pusch_pdu->mcs_index = sched_pusch->mcs;
1140 1141
    pusch_pdu->mcs_table = ps->mcs_table;
    pusch_pdu->transform_precoding = ps->transform_precoding;
1142 1143
    if (ps->pusch_Config &&
	ps->pusch_Config->dataScramblingIdentityPUSCH)
1144
      pusch_pdu->data_scrambling_id = *ps->pusch_Config->dataScramblingIdentityPUSCH;
1145 1146 1147 1148
    else
      pusch_pdu->data_scrambling_id = *scc->physCellId;
    pusch_pdu->nrOfLayers = 1;

1149
    /* FAPI: DMRS */
1150 1151
    pusch_pdu->ul_dmrs_symb_pos = ps->ul_dmrs_symb_pos;
    pusch_pdu->dmrs_config_type = ps->dmrs_config_type;
1152
    if (pusch_pdu->transform_precoding) { // transform precoding disabled
1153 1154
      long *scramblingid=NULL;
      if (ps->NR_DMRS_UplinkConfig && pusch_pdu->scid == 0)
1155
        scramblingid = ps->NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0;
1156
      else if (ps->NR_DMRS_UplinkConfig)
1157
        scramblingid = ps->NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID1;
1158 1159 1160 1161 1162 1163 1164
      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;
1165
      if (ps->NR_DMRS_UplinkConfig && ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity != NULL)
1166
        pusch_pdu->pusch_identity = *ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity;
1167
      else if (ps->NR_DMRS_UplinkConfig)
1168 1169
        pusch_pdu->pusch_identity = *scc->physCellId;
    }
1170
    pusch_pdu->scid = 0;      // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1]
1171
    pusch_pdu->num_dmrs_cdm_grps_no_data = ps->num_dmrs_cdm_grps_no_data;
1172 1173
    pusch_pdu->dmrs_ports = 1;

1174 1175 1176 1177 1178
    /* 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;
1179
    if (ps->pusch_Config==NULL || ps->pusch_Config->frequencyHopping==NULL)
1180 1181 1182 1183 1184
      pusch_pdu->frequency_hopping = 0;
    else
      pusch_pdu->frequency_hopping = 1;

    /* FAPI: Resource Allocation in time domain */
1185 1186
    pusch_pdu->start_symbol_index = ps->startSymbolIndex;
    pusch_pdu->nr_of_symbols = ps->nrOfSymbols;
1187 1188 1189 1190 1191

    /* PUSCH PDU */
    pusch_pdu->pusch_data.rv_index = nr_rv_round_map[cur_harq->round];
    pusch_pdu->pusch_data.harq_process_id = harq_id;
    pusch_pdu->pusch_data.new_data_indicator = cur_harq->ndi;
1192
    pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size;
1193 1194
    pusch_pdu->pusch_data.num_cb = 0; //CBG not supported

1195 1196 1197 1198 1199 1200 1201 1202
    /* 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
1203 1204
      if ((ps->NR_DMRS_UplinkConfig==NULL) || ((ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceGroupHopping == NULL) &&
					       (ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceHopping == NULL)))
1205 1206 1207 1208 1209 1210 1211 1212 1213
        pusch_pdu->dfts_ofdm.low_papr_sequence_number = 0;
      else
        AssertFatal(1==0,"SequenceGroupHopping or sequenceHopping are NOT Supported\n");

      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, ps->mcs_table);
    }

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

1214
    /* PUSCH PTRS */
1215
    if (ps->NR_DMRS_UplinkConfig && ps->NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) {
1216
      bool valid_ptrs_setup = false;
1217
      pusch_pdu->pusch_ptrs.ptrs_ports_list   = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t));
1218 1219 1220 1221 1222 1223 1224 1225
      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
      }
1226 1227 1228 1229
    }
    else{
      pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS
    }
1230

1231 1232
    /* look up the PDCCH PDU for this BWP and CORESET. If it does not exist,
     * create it */
1233 1234 1235 1236
    const int bwpid = sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0;
    NR_SearchSpace_t *ss = sched_ctrl->active_bwp ? sched_ctrl->search_space: RC.nrmac[module_id]->sched_ctrlCommon->search_space;
    NR_ControlResourceSet_t *coreset = sched_ctrl->active_bwp? sched_ctrl->coreset: RC.nrmac[module_id]->sched_ctrlCommon->coreset;
    const int coresetid = coreset->controlResourceSetId;
1237 1238 1239 1240 1241 1242 1243 1244
    nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = pdcch_pdu_bwp_coreset[bwpid][coresetid];
    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;
1245
      nr_configure_pdcch(pdcch_pdu, ss, coreset, scc, sched_ctrl->active_bwp);
1246 1247
      pdcch_pdu_bwp_coreset[bwpid][coresetid] = pdcch_pdu;
    }
1248

1249
    LOG_D(NR_MAC,"Configuring ULDCI/PDCCH in %d.%d\n", frame,slot);
1250

1251 1252 1253 1254
    /* 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;
1255 1256 1257
    if (coreset->pdcch_DMRS_ScramblingID &&
        ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) {
      dci_pdu->ScramblingId = *coreset->pdcch_DMRS_ScramblingID;
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
      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));
1270 1271 1272 1273 1274 1275
    NR_CellGroupConfig_t *CellGroup = UE_info->CellGroup[UE_id];
    int n_ubwp=1;
    if (CellGroup && CellGroup->spCellConfig && CellGroup->spCellConfig->spCellConfigDedicated && 
	CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig &&
	CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList)
      n_ubwp = CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count;
1276

1277
    config_uldci(sched_ctrl->active_ubwp,
1278
		 scc,
1279
                 pusch_pdu,
1280
                 &uldci_payload,
1281
                 ps->dci_format,
1282
                 ps->time_domain_allocation,
1283 1284
                 UE_info->UE_sched_ctrl[UE_id].tpc0,
                 n_ubwp,
1285
                 bwpid);
1286
    fill_dci_pdu_rel15(scc,
1287
                       CellGroup,
1288 1289
                       dci_pdu,
                       &uldci_payload,
1290 1291
                       ps->dci_format,
                       rnti_types[0],
1292
                       pusch_pdu->bwp_size,
1293
                       bwpid);
1294

Robert Schmidt's avatar
Robert Schmidt committed
1295
    memset(sched_pusch, 0, sizeof(*sched_pusch));
1296
  }
1297
}