gNB_scheduler.c 20.1 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
/*
 * 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.c
 * \brief gNB scheduler top level function operates on per subframe basis
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
24 25 26
 * \author  Navid Nikaein and Raymond Knopp, WEI-TAI CHEN
 * \date 2010 - 2014, 2018
 * \email: navid.nikaein@eurecom.fr, kroempa@gmail.com
27
 * \version 0.5
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
28
 * \company Eurecom, NTUST
29 30 31 32 33 34
 * @ingroup _mac

 */

#include "assertions.h"

35 36
#include "NR_MAC_COMMON/nr_mac_extern.h"
#include "NR_MAC_gNB/mac_proto.h"
37

Raymond Knopp's avatar
Raymond Knopp committed
38 39
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
40 41 42 43
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"

44
#include "RRC/NR/nr_rrc_extern.h"
45 46 47 48

//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"

49
#include "openair1/PHY/defs_gNB.h"
50
#include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h"
51

52 53
#include "intertask_interface.h"

54
#include "executables/softmodem-common.h"
Mahesh's avatar
Mahesh committed
55
#include "nfapi/oai_integration/vendor_ext.h"
56

57 58
uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 };

59
void clear_mac_stats(gNB_MAC_INST *gNB) {
60
  memset((void*)gNB->UE_info.mac_stats,0,MAX_MOBILES_PER_GNB*sizeof(NR_mac_stats_t));
61 62
}

ChiehChun's avatar
ChiehChun committed
63 64
void dump_mac_stats(gNB_MAC_INST *gNB)
{
65
  NR_UE_info_t *UE_info = &gNB->UE_info;
ChiehChun's avatar
ChiehChun committed
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
  int num = 1;
  for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
    LOG_I(MAC, "UE ID %d RNTI %04x (%d/%d)\n", UE_id, UE_info->rnti[UE_id], num++, UE_info->num_UEs);
    const NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id];
    LOG_I(MAC, "UE %d: dlsch_rounds %d/%d/%d/%d, dlsch_errors %d\n",
          UE_id,
          stats->dlsch_rounds[0], stats->dlsch_rounds[1],
          stats->dlsch_rounds[2], stats->dlsch_rounds[3], stats->dlsch_errors);
    LOG_I(MAC, "UE %d: dlsch_total_bytes %d\n", UE_id, stats->dlsch_total_bytes);
    LOG_I(MAC, "UE %d: ulsch_rounds %d/%d/%d/%d, ulsch_errors %d\n",
          UE_id,
          stats->ulsch_rounds[0], stats->ulsch_rounds[1],
          stats->ulsch_rounds[2], stats->ulsch_rounds[3], stats->ulsch_errors);
    LOG_I(MAC,
          "UE %d: ulsch_total_bytes_scheduled %d, ulsch_total_bytes_received %d\n",
          UE_id,
          stats->ulsch_total_bytes_scheduled, stats->ulsch_total_bytes_rx);
    for (int lc_id = 0; lc_id < 63; lc_id++) {
      if (stats->lc_bytes_tx[lc_id] > 0)
        LOG_I(MAC, "UE %d: LCID %d: %d bytes TX\n", UE_id, lc_id, stats->lc_bytes_tx[lc_id]);
      if (stats->lc_bytes_rx[lc_id] > 0)
        LOG_I(MAC, "UE %d: LCID %d: %d bytes RX\n", UE_id, lc_id, stats->lc_bytes_rx[lc_id]);
88 89 90 91
    }
  }
}

r.karey's avatar
r.karey committed
92

vr.devendra's avatar
vr.devendra committed
93
void clear_nr_nfapi_information(gNB_MAC_INST *gNB,
94 95 96
                                int CC_idP,
                                frame_t frameP,
                                sub_frame_t slotP){
97
  NR_ServingCellConfigCommon_t *scc = gNB->common_channels->ServingCellConfigCommon;
98
  const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
99

Raymond Knopp's avatar
Raymond Knopp committed
100
  nfapi_nr_dl_tti_request_t    *DL_req = &gNB->DL_req[0];
101
  nfapi_nr_dl_tti_pdcch_pdu_rel15_t ***pdcch = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t ***)gNB->pdcch_pdu_idx[CC_idP];
102 103
  nfapi_nr_ul_tti_request_t    *future_ul_tti_req =
      &gNB->UL_tti_req_ahead[CC_idP][(slotP + num_slots - 1) % num_slots];
104
  nfapi_nr_ul_dci_request_t    *UL_dci_req = &gNB->UL_dci_req[0];
Raymond Knopp's avatar
Raymond Knopp committed
105
  nfapi_nr_tx_data_request_t   *TX_req = &gNB->TX_req[0];
106 107
  gNB->pdu_index[CC_idP] = 0;

108
  if (NFAPI_MODE == NFAPI_MONOLITHIC || NFAPI_MODE == NFAPI_MODE_PNF) { // monolithic or PNF
109

Raymond Knopp's avatar
Raymond Knopp committed
110 111 112 113 114
    DL_req[CC_idP].SFN                                   = frameP;
    DL_req[CC_idP].Slot                                  = slotP;
    DL_req[CC_idP].dl_tti_request_body.nPDUs             = 0;
    DL_req[CC_idP].dl_tti_request_body.nGroup            = 0;
    //DL_req[CC_idP].dl_tti_request_body.transmission_power_pcfich           = 6000;
115
    memset(pdcch, 0, sizeof(**pdcch) * MAX_NUM_BWP * MAX_NUM_CORESET);
116

117 118 119
    UL_dci_req[CC_idP].SFN                         = frameP;
    UL_dci_req[CC_idP].Slot                        = slotP;
    UL_dci_req[CC_idP].numPdus                     = 0;
120

121 122 123 124 125 126 127 128
    /* advance last round's future UL_tti_req to be ahead of current frame/slot */
    future_ul_tti_req->SFN = (slotP == 0 ? frameP : frameP + 1) % 1024;
    /* future_ul_tti_req->Slot is fixed! */
    future_ul_tti_req->n_pdus = 0;
    future_ul_tti_req->n_ulsch = 0;
    future_ul_tti_req->n_ulcch = 0;
    future_ul_tti_req->n_group = 0;

129 130
    /* UL_tti_req is a simple pointer into the current UL_tti_req_ahead, i.e.,
     * it walks over UL_tti_req_ahead in a circular fashion */
131
    gNB->UL_tti_req[CC_idP] = &gNB->UL_tti_req_ahead[CC_idP][slotP];
132 133

    TX_req[CC_idP].Number_of_PDUs                  = 0;
134 135
  }
}
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
136
/*
137 138
void check_nr_ul_failure(module_id_t module_idP,
                         int CC_id,
139
                         int UE_id,
140
                         frame_t frameP,
141
                         sub_frame_t slotP) {
142

143
  NR_UE_info_t                 *UE_info  = &RC.nrmac[module_idP]->UE_info;
Raymond Knopp's avatar
Raymond Knopp committed
144
  nfapi_nr_dl_dci_request_t  *DL_req   = &RC.nrmac[module_idP]->DL_req[0];
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
145 146
  uint16_t                      rnti      = UE_RNTI(module_idP, UE_id);
  NR_COMMON_channels_t          *cc       = RC.nrmac[module_idP]->common_channels;
147 148

  // check uplink failure
149 150
  if ((UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 0) &&
      (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 0)) {
151
    LOG_I(MAC, "UE %d rnti %x: UL Failure timer %d \n", UE_id, rnti,
152 153 154
    UE_info->UE_sched_ctrl[UE_id].ul_failure_timer);
    if (UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent == 0) {
      UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 1;
155 156

      // add a format 1A dci for this UE to request an RA procedure (only one UE per subframe)
Raymond Knopp's avatar
Raymond Knopp committed
157 158
      nfapi_nr_dl_dci_request_pdu_t *dl_config_pdu                    = &DL_req[CC_id].dl_tti_request_body.dl_config_pdu_list[DL_req[CC_id].dl_tti_request_body.number_pdu];
      memset((void *) dl_config_pdu, 0,sizeof(nfapi_dl_dci_request_pdu_t));
159 160
      dl_config_pdu->pdu_type                                         = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
      dl_config_pdu->pdu_size                                         = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu));
Raymond Knopp's avatar
Raymond Knopp committed
161
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag                = NFAPI_DL_DCI_REQUEST_DCI_DL_PDU_REL8_TAG;
162 163
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format            = NFAPI_DL_DCI_FORMAT_1A;
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level     = get_aggregation(get_bw_index(module_idP, CC_id),
164
                      UE_info->UE_sched_ctrl[UE_id].
165 166 167 168 169 170 171 172 173
                      dl_cqi[CC_id], format1A);
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                  = rnti;
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type             = 1;  // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power    = 6000; // equal to RS power

      AssertFatal((cc[CC_id].mib->message.dl_Bandwidth >= 0) && (cc[CC_id].mib->message.dl_Bandwidth < 6),
      "illegal dl_Bandwidth %d\n",
      (int) cc[CC_id].mib->message.dl_Bandwidth);
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = nr_pdcch_order_table[cc[CC_id].mib->message.dl_Bandwidth];
Raymond Knopp's avatar
Raymond Knopp committed
174 175 176
      DL_req[CC_id].dl_tti_request_body.number_dci++;
      DL_req[CC_id].dl_tti_request_body.number_pdu++;
      DL_req[CC_id].dl_tti_request_body.tl.tag                      = NFAPI_DL_TTI_REQUEST_BODY_TAG;
177 178 179
      LOG_I(MAC,
      "UE %d rnti %x: sending PDCCH order for RAPROC (failure timer %d), resource_block_coding %d \n",
      UE_id, rnti,
180
      UE_info->UE_sched_ctrl[UE_id].ul_failure_timer,
181 182 183 184 185 186
      dl_config_pdu->dci_dl_pdu.
      dci_dl_pdu_rel8.resource_block_coding);
    } else {    // ra_pdcch_sent==1
      LOG_I(MAC,
      "UE %d rnti %x: sent PDCCH order for RAPROC waiting (failure timer %d) \n",
      UE_id, rnti,
187 188
      UE_info->UE_sched_ctrl[UE_id].ul_failure_timer);
      if ((UE_info->UE_sched_ctrl[UE_id].ul_failure_timer % 40) == 0) UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 0;  // resend every 4 frames
189 190
    }

191
    UE_info->UE_sched_ctrl[UE_id].ul_failure_timer++;
192
    // check threshold
193
    if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 20000) {
194 195 196 197 198
      // inform RRC of failure and clear timer
      LOG_I(MAC,
      "UE %d rnti %x: UL Failure after repeated PDCCH orders: Triggering RRC \n",
      UE_id, rnti);
      mac_eNB_rrc_ul_failure(module_idP, CC_id, frameP, subframeP,rnti);
199 200
      UE_info->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
      UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync   = 1;
201 202 203 204 205 206 207 208 209 210 211

      //Inform the controller about the UE deactivation. Should be moved to RRC agent in the future
      if (rrc_agent_registered[module_idP]) {
        LOG_W(MAC, "notify flexran Agent of UE state change\n");
        agent_rrc_xface[module_idP]->flexran_agent_notify_ue_state_change(module_idP,
            rnti, PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_DEACTIVATED);
      }
    }
  }       // ul_failure_timer>0

}
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
212
*/
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
213
/*
214 215 216
void schedule_nr_SRS(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
{
  gNB_MAC_INST *gNB = RC.nrmac[module_idP];
217
  NR_UE_info_t *UE_info = &gNB->UE_info;
218 219
  nfapi_ul_config_request_body_t *ul_req;
  int CC_id, UE_id;
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
220
  NR_COMMON_channels_t *cc = RC.nrmac[module_idP]->common_channels;
221 222 223 224 225
  SoundingRS_UL_ConfigCommon_t *soundingRS_UL_ConfigCommon;
  struct SoundingRS_UL_ConfigDedicated *soundingRS_UL_ConfigDedicated;
  uint8_t TSFC;
  uint16_t deltaTSFC;   // bitmap
  uint8_t srs_SubframeConfig;
226

227 228 229
  // table for TSFC (Period) and deltaSFC (offset)
  const uint16_t deltaTSFCTabType1[15][2] = { {1, 1}, {1, 2}, {2, 2}, {1, 5}, {2, 5}, {4, 5}, {8, 5}, {3, 5}, {12, 5}, {1, 10}, {2, 10}, {4, 10}, {8, 10}, {351, 10}, {383, 10} };  // Table 5.5.3.3-2 3GPP 36.211 FDD
  const uint16_t deltaTSFCTabType2[14][2] = { {2, 5}, {6, 5}, {10, 5}, {18, 5}, {14, 5}, {22, 5}, {26, 5}, {30, 5}, {70, 10}, {74, 10}, {194, 10}, {326, 10}, {586, 10}, {210, 10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD
230

231
  uint16_t srsPeriodicity, srsOffset;
232

233 234 235 236 237 238 239 240 241 242 243 244 245 246
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    soundingRS_UL_ConfigCommon = &cc[CC_id].radioResourceConfigCommon->soundingRS_UL_ConfigCommon;
    // check if SRS is enabled in this frame/subframe
    if (soundingRS_UL_ConfigCommon) {
      srs_SubframeConfig = soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig;
      if (cc[CC_id].tdd_Config == NULL) { // FDD
  deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0];
  TSFC = deltaTSFCTabType1[srs_SubframeConfig][1];
      } else {    // TDD
  deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0];
  TSFC = deltaTSFCTabType2[srs_SubframeConfig][1];
      }
      // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC
      uint16_t tmp = (subframeP % TSFC);
247

248 249 250
      if ((1 << tmp) & deltaTSFC) {
  // This is an SRS subframe, loop over UEs
  for (UE_id = 0; UE_id < MAX_MOBILES_PER_GNB; UE_id++) {
251
    if (!RC.nrmac[module_idP]->UE_info.active[UE_id]) continue;
252 253 254
    ul_req = &RC.nrmac[module_idP]->UL_req[CC_id].ul_config_request_body;
    // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet
    if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) continue;
255

256
    AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL,
257 258
          "physicalConfigDedicated is null for UE %d\n",
          UE_id);
259

260
    if ((soundingRS_UL_ConfigDedicated = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated) != NULL) {
261 262 263 264 265 266 267 268 269 270 271 272 273 274
      if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) {
        get_srs_pos(&cc[CC_id],
        soundingRS_UL_ConfigDedicated->choice.
        setup.srs_ConfigIndex,
        &srsPeriodicity, &srsOffset);
        if (((10 * frameP + subframeP) % srsPeriodicity) == srsOffset) {
    // Program SRS
    ul_req->srs_present = 1;
    nfapi_ul_config_request_pdu_t * ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
    memset((void *) ul_config_pdu, 0, sizeof(nfapi_ul_config_request_pdu_t));
    ul_config_pdu->pdu_type =  NFAPI_UL_CONFIG_SRS_PDU_TYPE;
    ul_config_pdu->pdu_size =  2 + (uint8_t) (2 + sizeof(nfapi_ul_config_srs_pdu));
    ul_config_pdu->srs_pdu.srs_pdu_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG;
    ul_config_pdu->srs_pdu.srs_pdu_rel8.size = (uint8_t)sizeof(nfapi_ul_config_srs_pdu);
275
    ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti;
276 277 278 279 280 281 282 283 284 285 286 287
    ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth;
    ul_config_pdu->srs_pdu.srs_pdu_rel8.frequency_domain_position = soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition;
    ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_hopping_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;;
    ul_config_pdu->srs_pdu.srs_pdu_rel8.transmission_comb = soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb;
    ul_config_pdu->srs_pdu.srs_pdu_rel8.i_srs = soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex;
    ul_config_pdu->srs_pdu.srs_pdu_rel8.sounding_reference_cyclic_shift = soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift;    //              ul_config_pdu->srs_pdu.srs_pdu_rel10.antenna_port                   = ;//
    //              ul_config_pdu->srs_pdu.srs_pdu_rel13.number_of_combs                = ;//
    RC.nrmac[module_idP]->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP;
    RC.nrmac[module_idP]->UL_req[CC_id].header.message_id = NFAPI_UL_CONFIG_REQUEST;
    ul_req->number_of_pdus++;
        } // if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset)
      } // if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup)
288
    }   // if ((soundingRS_UL_ConfigDedicated = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL)
289 290
  }   // for (UE_id ...
      }     // if((1<<tmp) & deltaTSFC)
291

292 293 294
    }     // SRS config
  }
}
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
295
*/
296

297 298
bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) {
  return (bitmap >> slot) & 0x01;
299
}
300 301


302
void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
303 304
                               frame_t frame,
                               sub_frame_t slot){
305

306
  protocol_ctxt_t   ctxt;
307
  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP);
308
 
309
  int nb_periods_per_frame;
310

311
  const int bwp_id = 1;
312

313 314
  gNB_MAC_INST *gNB = RC.nrmac[module_idP];
  NR_COMMON_channels_t *cc = gNB->common_channels;
315
  NR_ServingCellConfigCommon_t        *scc     = cc->ServingCellConfigCommon;
316
  NR_TDD_UL_DL_Pattern_t *tdd_pattern = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
317

318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
  switch(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity) {
    case 0:
      nb_periods_per_frame = 20; // 10ms/0p5ms
      break;

    case 1:
      nb_periods_per_frame = 16; // 10ms/0p625ms
      break;

    case 2:
      nb_periods_per_frame = 10; // 10ms/1ms
      break;

    case 3:
      nb_periods_per_frame = 8; // 10ms/1p25ms
      break;

    case 4:
      nb_periods_per_frame = 5; // 10ms/2ms
      break;

    case 5:
      nb_periods_per_frame = 4; // 10ms/2p5ms
      break;

    case 6:
      nb_periods_per_frame = 2; // 10ms/5ms
      break;

    case 7:
      nb_periods_per_frame = 1; // 10ms/10ms
      break;

    default:
352
      AssertFatal(1==0,"Undefined tdd period %ld\n", scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity);
353 354
  }

355
  int num_slots_per_tdd = (nr_slots_per_frame[*scc->ssbSubcarrierSpacing])/nb_periods_per_frame;
356

357
  const int nr_ulmix_slots = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0);
358

359
  start_meas(&RC.nrmac[module_idP]->eNB_scheduler);
Rakesh's avatar
Rakesh committed
360
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN);
361
  pdcp_run(&ctxt);
Cedric Roux's avatar
Cedric Roux committed
362
  /* send tick to RLC and RRC every ms */
363 364 365
  if ((slot & ((1 << *scc->ssbSubcarrierSpacing) - 1)) == 0) {
    void nr_rlc_tick(int frame, int subframe);
    nr_rlc_tick(frame, slot >> *scc->ssbSubcarrierSpacing);
Cedric Roux's avatar
Cedric Roux committed
366
    nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing);
367
  }
368

369
#define BIT(x) (1 << (x))
Robert Schmidt's avatar
Robert Schmidt committed
370 371
  const uint64_t dlsch_in_slot_bitmap = BIT( 1) | BIT( 2) | BIT( 3) | BIT( 4) | BIT( 5) | BIT( 6)
                                      | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16);
ChiehChun's avatar
ChiehChun committed
372
  const uint64_t ulsch_in_slot_bitmap = BIT( 8) | BIT(18);
373

374 375
  memset(RC.nrmac[module_idP]->cce_list[bwp_id][0],0,MAX_NUM_CCE*sizeof(int)); // coreset0
  memset(RC.nrmac[module_idP]->cce_list[bwp_id][1],0,MAX_NUM_CCE*sizeof(int)); // coresetid 1
376 377 378 379
  NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info;
  for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id])
    for (int i=0; i<MAX_NUM_CORESET; i++)
      UE_info->num_pdcch_cand[UE_id][i] = 0;
380
  for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
381
    //mbsfn_status[CC_id] = 0;
Mahesh's avatar
Mahesh committed
382

383
    // clear vrb_maps
384
    memset(cc[CC_id].vrb_map, 0, sizeof(uint16_t) * MAX_BWP_SIZE);
Robert Schmidt's avatar
Robert Schmidt committed
385
    // clear last scheduled slot's content (only)!
386
    const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
Robert Schmidt's avatar
Robert Schmidt committed
387 388
    const int last_slot = (slot + num_slots - 1) % num_slots;
    uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL;
389
    memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE);
390

391
    clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot);
392
  }
393

Mahesh's avatar
Mahesh committed
394

395
  if ((slot == 0) && (frame & 127) == 0) dump_mac_stats(RC.nrmac[module_idP]);
396

397
  // This schedules MIB
398
  schedule_nr_mib(module_idP, frame, slot, nr_slots_per_frame[*scc->ssbSubcarrierSpacing]);
399

400
  // This schedules SIB1
401
  if ( get_softmodem_params()->sa == 1 )
402
    schedule_nr_sib1(module_idP, frame, slot);
403

404

405
  // This schedule PRACH if we are not in phy_test mode
406 407 408 409 410 411 412
  if (get_softmodem_params()->phy_test == 0) {
    /* we need to make sure that resources for PRACH are free. To avoid that
       e.g. PUSCH has already been scheduled, make sure we schedule before
       anything else: below, we simply assume an advance one frame (minus one
       slot, because otherwise we would allocate the current slot in
       UL_tti_req_ahead), but be aware that, e.g., K2 is allowed to be larger
       (schedule_nr_prach will assert if resources are not free). */
413 414 415
    const sub_frame_t n_slots_ahead = nr_slots_per_frame[*scc->ssbSubcarrierSpacing] - 1;
    const frame_t f = (frame + (slot + n_slots_ahead) / nr_slots_per_frame[*scc->ssbSubcarrierSpacing]) % 1024;
    const sub_frame_t s = (slot + n_slots_ahead) % nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
416 417
    schedule_nr_prach(module_idP, f, s);
  }
418

419 420
  // This schedule SR
  // TODO
421

422
  // Schedule CSI measurement reporting: check in slot 0 for the whole frame
423 424
  if (slot == 0)
    nr_csi_meas_reporting(module_idP, frame, slot);
425

426 427 428
  // This schedule RA procedure if not in phy_test mode
  // Otherwise already consider 5G already connected
  if (get_softmodem_params()->phy_test == 0) {
429
    nr_schedule_RA(module_idP, frame, slot);
430
  }
431

432
  // This schedules the DCI for Uplink and subsequently PUSCH
ChiehChun's avatar
ChiehChun committed
433
  {
434
    nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap);
435 436
  }

437
  // This schedules the DCI for Downlink and PDSCH
438
  if (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot))
439
    nr_schedule_ue_spec(module_idP, frame, slot);
440

Laurent's avatar
Laurent committed
441

442
  nr_schedule_pucch(module_idP, frame, slot);
443

444
  stop_meas(&RC.nrmac[module_idP]->eNB_scheduler);
Rakesh's avatar
Rakesh committed
445
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT);
Raymond Knopp's avatar
Raymond Knopp committed
446
}