gNB_scheduler_primitives.c 23.5 KB
Newer Older
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
22 23
/*! \file gNB_scheduler_primitives.c
 * \brief primitives used by gNB for BCH, RACH, ULSCH, DLSCH scheduling
24 25 26
 * \author  Raymond Knopp, Guy De Souza
 * \date 2018, 2019
 * \email: knopp@eurecom.fr, desouza@eurecom.fr
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
27
 * \version 1.0
28
 * \company Eurecom
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
29 30 31 32 33 34
 * @ingroup _mac

 */

#include "assertions.h"

WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
35
#include "LAYER2/MAC/mac.h"
36
#include "LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
37 38
#include "LAYER2/MAC/mac_extern.h"

WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
39
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
Raymond Knopp's avatar
Raymond Knopp committed
40 41
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
42 43 44
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
45 46

#include "RRC/LTE/rrc_extern.h"
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
47
#include "RRC/NR/nr_rrc_extern.h"
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
48
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
49 50 51 52 53 54 55 56 57 58 59

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

#if defined(ENABLE_ITTI)
#include "intertask_interface.h"
#endif

#include "T.h"

#define ENABLE_MAC_PAYLOAD_DEBUG
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
60
#define DEBUG_gNB_SCHEDULER 1
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
61 62 63 64 65 66 67

#include "common/ran_context.h"

extern RAN_CONTEXT_t RC;

extern int n_active_slices;

68
  // Note the 2 scs values in the table names represent resp. scs_common and pdcch_scs
Raymond Knopp's avatar
Raymond Knopp committed
69
/// LUT for the number of symbols in the coreset indexed by coreset index (4 MSB rmsi_pdcch_config)
70 71 72 73 74 75 76 77
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_15_15[15] = {2,2,2,3,3,3,1,1,2,2,3,3,1,2,3};
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_15_30[14] = {2,2,2,2,3,3,3,3,1,1,2,2,3,3};
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_30_15_b40Mhz[9] = {1,1,2,2,3,3,1,2,3};
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_30_15_a40Mhz[9] = {1,2,3,1,1,2,2,3,3};
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_30_30_b40Mhz[16] = {2,2,2,2,2,3,3,3,3,3,1,1,1,2,2,2}; // below 40Mhz bw
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_30_30_a40Mhz[10] = {2,2,3,3,1,1,2,2,3,3}; // above 40Mhz bw
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_120_60[12] = {1,1,2,2,3,3,1,2,1,1,1,1};

Raymond Knopp's avatar
Raymond Knopp committed
78
/// LUT for the number of RBs in the coreset indexed by coreset index
79 80 81 82 83 84 85 86 87 88
uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_15_15[15] = {0,2,4,0,2,4,12,16,12,16,12,16,38,38,38};
uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_15_30[14] = {5,6,7,8,5,6,7,8,18,20,18,20,18,20};
uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_30_15_b40Mhz[9] = {2,6,2,6,2,6,28,28,28};
uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_30_15_a40Mhz[9] = {4,4,4,0,56,0,56,0,56};
uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_30_30_b40Mhz[16] = {0,1,2,3,4,0,1,2,3,4,12,14,16,12,14,16};
uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_30_30_a40Mhz[10] = {0,4,0,4,0,28,0,28,0,28};
int8_t  nr_coreset_rb_offset_pdcch_type_0_scs_120_60[12] = {0,8,0,8,0,8,28,28,-1,49,-1,97};
int8_t  nr_coreset_rb_offset_pdcch_type_0_scs_120_120[8] = {0,4,14,14,-1,24,-1,48};
int8_t  nr_coreset_rb_offset_pdcch_type_0_scs_240_120[8] = {0,8,0,8,-1,25,-1,49};

Raymond Knopp's avatar
Raymond Knopp committed
89
/// LUT for monitoring occasions param O indexed by ss index (4 LSB rmsi_pdcch_config)
90
  // Note: scaling is used to avoid decimal values for O and M, original values commented
Raymond Knopp's avatar
Raymond Knopp committed
91
uint8_t nr_ss_param_O_type_0_mux1_FR1[16] = {0,0,2,2,5,5,7,7,0,5,0,0,2,2,5,5};
92 93
uint8_t nr_ss_param_O_type_0_mux1_FR2[14] = {0,0,5,5,5,5,0,5,5,15,15,15,0,5}; //{0,0,2.5,2.5,5,5,0,2.5,5,7.5,7.5,7.5,0,5}
uint8_t nr_ss_scale_O_mux1_FR2[14] = {0,0,1,1,0,0,0,1,0,1,1,1,0,0};
94

Raymond Knopp's avatar
Raymond Knopp committed
95 96 97
/// LUT for number of SS sets per slot indexed by ss index
uint8_t nr_ss_sets_per_slot_type_0_FR1[16] = {1,2,1,2,1,2,1,2,1,1,1,1,1,1,1,1};
uint8_t nr_ss_sets_per_slot_type_0_FR2[14] = {1,2,1,2,1,2,2,2,2,1,2,2,1,1};
98

Raymond Knopp's avatar
Raymond Knopp committed
99
/// LUT for monitoring occasions param M indexed by ss index
100 101 102 103
uint8_t nr_ss_param_M_type_0_mux1_FR1[16] = {1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1}; //{1,0.5,1,0.5,1,0.5,1,0.5,2,2,1,1,1,1,1,1}
uint8_t nr_ss_scale_M_mux1_FR1[16] = {0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0};
uint8_t nr_ss_param_M_type_0_mux1_FR2[14] = {1,1,1,1,1,1,1,1,1,1,1,1,2,2}; //{1,0.5,1,0.5,1,0.5,0.5,0.5,0.5,1,0.5,0.5,2,2}
uint8_t nr_ss_scale_M_mux1_FR2[14] = {0,1,0,1,0,1,1,1,1,0,1,1,0,0};
104

Raymond Knopp's avatar
Raymond Knopp committed
105 106
/// LUT for SS first symbol index indexed by ss index
uint8_t nr_ss_first_symb_idx_type_0_mux1_FR1[8] = {0,0,1,2,1,2,1,2};
107 108 109 110 111 112
  // Mux pattern type 2
uint8_t nr_ss_first_symb_idx_scs_120_60_mux2[4] = {0,1,6,7};
uint8_t nr_ss_first_symb_idx_scs_240_120_set1_mux2[6] = {0,1,2,3,0,1};
  // Mux pattern type 3
uint8_t nr_ss_first_symb_idx_scs_120_120_mux3[4] = {4,8,2,6};

113 114 115
/// Search space max values indexed by scs
uint8_t nr_max_number_of_candidates_per_slot[4] = {44, 36, 22, 20};
uint8_t nr_max_number_of_cces_per_slot[4] = {56, 56, 48, 32};
Raymond Knopp's avatar
Raymond Knopp committed
116

117 118 119 120 121 122 123 124 125
static inline uint8_t get_max_candidates(uint8_t scs) {
  AssertFatal(scs<4, "Invalid PDCCH subcarrier spacing %d\n", scs);
  return (nr_max_number_of_candidates_per_slot[scs]);
}

static inline uint8_t get_max_cces(uint8_t scs) {
  AssertFatal(scs<4, "Invalid PDCCH subcarrier spacing %d\n", scs);
  return (nr_max_number_of_cces_per_slot[scs]);
} 
126

127
int is_nr_UL_slot(NR_COMMON_channels_t * ccP, int slot){
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
128

129
    return (0);
Raymond Knopp's avatar
Raymond Knopp committed
130
}
Raymond Knopp's avatar
Raymond Knopp committed
131

132 133 134 135 136 137
void nr_configure_css_dci_initial(nfapi_nr_dl_config_pdcch_parameters_rel15_t* pdcch_params,
				  nr_scs_e scs_common,
				  nr_scs_e pdcch_scs,
				  nr_frequency_range_e freq_range,
				  uint8_t rmsi_pdcch_config,
				  uint8_t ssb_idx,
138 139 140
				  uint8_t k_ssb,
				  uint16_t sfn_ssb,
				  uint8_t n_ssb, /*slot index overlapping the corresponding SSB index*/
141 142
				  uint16_t nb_slots_per_frame,
				  uint16_t N_RB)
Raymond Knopp's avatar
Raymond Knopp committed
143 144 145 146
{
  uint8_t O, M;
  uint8_t ss_idx = rmsi_pdcch_config&0xf;
  uint8_t cset_idx = (rmsi_pdcch_config>>4)&0xf;
147 148
  uint8_t mu = scs_common;
  uint8_t O_scale=0, M_scale=0; // used to decide if the values of O and M need to be divided by 2
Raymond Knopp's avatar
Raymond Knopp committed
149 150 151 152 153

  /// Coreset params
  switch(scs_common) {

    case kHz15:
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175

      switch(pdcch_scs) {
        case kHz15:
          AssertFatal(cset_idx<15,"Coreset index %d reserved for scs kHz15/kHz15\n", cset_idx);
          pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
          pdcch_params->n_rb = (cset_idx < 6)? 24 : (cset_idx < 12)? 48 : 96;
          pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_15_15[cset_idx];
          pdcch_params->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_15_15[cset_idx];
        break;

        case kHz30:
          AssertFatal(cset_idx<14,"Coreset index %d reserved for scs kHz15/kHz30\n", cset_idx);
          pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
          pdcch_params->n_rb = (cset_idx < 8)? 24 : 48;
          pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_15_30[cset_idx];
          pdcch_params->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_15_15[cset_idx];
        break;

        default:
            AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);

      }
Raymond Knopp's avatar
Raymond Knopp committed
176 177 178 179 180 181 182
      break;

    case kHz30:

      if (N_RB < 106) { // Minimum 40Mhz bandwidth not satisfied
        switch(pdcch_scs) {
          case kHz15:
183 184 185 186 187 188
            AssertFatal(cset_idx<9,"Coreset index %d reserved for scs kHz30/kHz15\n", cset_idx);
            pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
            pdcch_params->n_rb = (cset_idx < 10)? 48 : 96;
            pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_15_b40Mhz[cset_idx];
            pdcch_params->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_15_b40Mhz[cset_idx];
          break;
Raymond Knopp's avatar
Raymond Knopp committed
189 190 191

          case kHz30:
            pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
192 193 194 195
            pdcch_params->n_rb = (cset_idx < 6)? 24 : 48;
            pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_30_b40Mhz[cset_idx];
            pdcch_params->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_30_b40Mhz[cset_idx];
          break;
Raymond Knopp's avatar
Raymond Knopp committed
196 197 198 199 200 201

          default:
            AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
        }
      }

202
      else { // above 40Mhz
Raymond Knopp's avatar
Raymond Knopp committed
203 204
        switch(pdcch_scs) {
          case kHz15:
205 206 207 208 209 210
            AssertFatal(cset_idx<9,"Coreset index %d reserved for scs kHz30/kHz15\n", cset_idx);
            pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
            pdcch_params->n_rb = (cset_idx < 3)? 48 : 96;
            pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_15_a40Mhz[cset_idx];
            pdcch_params->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_15_a40Mhz[cset_idx];
          break;
Raymond Knopp's avatar
Raymond Knopp committed
211 212

          case kHz30:
213
            AssertFatal(cset_idx<10,"Coreset index %d reserved for scs kHz30/kHz30\n", cset_idx);
Raymond Knopp's avatar
Raymond Knopp committed
214 215
            pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
            pdcch_params->n_rb = (cset_idx < 4)? 24 : 48;
216 217 218
            pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_30_a40Mhz[cset_idx];
            pdcch_params->rb_offset =  nr_coreset_rb_offset_pdcch_type_0_scs_30_30_a40Mhz[cset_idx];
          break;
Raymond Knopp's avatar
Raymond Knopp committed
219 220 221 222 223 224 225 226

          default:
            AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
        }
      }
      break;

    case kHz120:
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
      switch(pdcch_scs) {
        case kHz60:
          AssertFatal(cset_idx<12,"Coreset index %d reserved for scs kHz120/kHz60\n", cset_idx);
          pdcch_params->mux_pattern = (cset_idx < 8)?NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 : NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2;
          pdcch_params->n_rb = (cset_idx < 6)? 48 : (cset_idx < 8)? 96 : (cset_idx < 10)? 48 : 96;
          pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_120_60[cset_idx];
          pdcch_params->rb_offset = (nr_coreset_rb_offset_pdcch_type_0_scs_120_60[cset_idx]>0)?nr_coreset_rb_offset_pdcch_type_0_scs_120_60[cset_idx] :
          (k_ssb == 0)? -41 : -42;
        break;

        case kHz120:
          AssertFatal(cset_idx<8,"Coreset index %d reserved for scs kHz120/kHz120\n", cset_idx);
          pdcch_params->mux_pattern = (cset_idx < 4)?NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 : NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE3;
          pdcch_params->n_rb = (cset_idx < 2)? 24 : (cset_idx < 4)? 48 : (cset_idx < 6)? 24 : 48;
          pdcch_params->n_symb = (cset_idx == 2)? 1 : 2;
          pdcch_params->rb_offset = (nr_coreset_rb_offset_pdcch_type_0_scs_120_120[cset_idx]>0)? nr_coreset_rb_offset_pdcch_type_0_scs_120_120[cset_idx] :
          (k_ssb == 0)? -20 : -21;
        break;

        default:
            AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
      }
    break;

    case kHz240:
    switch(pdcch_scs) {
      case kHz60:
        AssertFatal(cset_idx<4,"Coreset index %d reserved for scs kHz240/kHz60\n", cset_idx);
        pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
        pdcch_params->n_rb = 96;
        pdcch_params->n_symb = (cset_idx < 2)? 1 : 2;
        pdcch_params->rb_offset = (cset_idx&1)? 16 : 0;
      break;

      case kHz120:
        AssertFatal(cset_idx<8,"Coreset index %d reserved for scs kHz240/kHz120\n", cset_idx);
        pdcch_params->mux_pattern = (cset_idx < 4)? NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 : NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2;
        pdcch_params->n_rb = (cset_idx < 4)? 48 : (cset_idx < 6)? 24 : 48;
        pdcch_params->n_symb = ((cset_idx==2)||(cset_idx==3))? 2 : 1;
        pdcch_params->rb_offset = (nr_coreset_rb_offset_pdcch_type_0_scs_240_120[cset_idx]>0)? nr_coreset_rb_offset_pdcch_type_0_scs_240_120[cset_idx] :
        (k_ssb == 0)? -41 : -42;
Raymond Knopp's avatar
Raymond Knopp committed
268 269
      break;

270 271 272 273 274
      default:
          AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
    }
    break;

Raymond Knopp's avatar
Raymond Knopp committed
275 276 277 278 279 280 281 282 283 284 285 286 287
  default:
    AssertFatal(1==0,"Invalid common subcarrier spacing %d\n", scs_common);

  }

  /// Search space params
  switch(pdcch_params->mux_pattern) {

    case NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1:
      if (freq_range == nr_FR1) {
        O = nr_ss_param_O_type_0_mux1_FR1[ss_idx];
        pdcch_params->nb_ss_sets_per_slot = nr_ss_sets_per_slot_type_0_FR1[ss_idx];
        M = nr_ss_param_M_type_0_mux1_FR1[ss_idx];
288
        M_scale = nr_ss_scale_M_mux1_FR1[ss_idx];
289
        pdcch_params->first_symbol = (ss_idx < 8)? ( (ssb_idx&1)? pdcch_params->n_symb : 0 ) : nr_ss_first_symb_idx_type_0_mux1_FR1[ss_idx - 8];
Raymond Knopp's avatar
Raymond Knopp committed
290 291 292 293 294
      }

      else {
        AssertFatal(ss_idx<14 ,"Invalid search space index for multiplexing type 1 and FR2 %d\n", ss_idx);
        O = nr_ss_param_O_type_0_mux1_FR2[ss_idx];
295
        O_scale = nr_ss_scale_O_mux1_FR2[ss_idx];
Raymond Knopp's avatar
Raymond Knopp committed
296 297
        pdcch_params->nb_ss_sets_per_slot = nr_ss_sets_per_slot_type_0_FR2[ss_idx];
        M = nr_ss_param_M_type_0_mux1_FR2[ss_idx];
298
        M_scale = nr_ss_scale_M_mux1_FR2[ss_idx];
Raymond Knopp's avatar
Raymond Knopp committed
299 300 301
        pdcch_params->first_symbol = (ss_idx < 12)? ( (ss_idx&1)? 7 : 0 ) : 0;
      }
      pdcch_params->nb_slots = 2;
302 303
      pdcch_params->sfn_mod2 = (CEILIDIV( (((O<<mu)>>O_scale) + ((ssb_idx*M)>>M_scale)), nb_slots_per_frame ) & 1)? 1 : 0;
      pdcch_params->first_slot = (((O<<mu)>>O_scale) + ((ssb_idx*M)>>M_scale)) % nb_slots_per_frame;
Raymond Knopp's avatar
Raymond Knopp committed
304

305
    break;
Raymond Knopp's avatar
Raymond Knopp committed
306 307

    case NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2:
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
      AssertFatal( ((scs_common==kHz120)&&(pdcch_scs==kHz60)) || ((scs_common==kHz240)&&(pdcch_scs==kHz120)),
      "Invalid scs_common/pdcch_scs combination %d/%d for Mux type 2\n", scs_common, pdcch_scs );
      AssertFatal(ss_idx==0, "Search space index %d reserved for scs_common/pdcch_scs combination %d/%d", ss_idx, scs_common, pdcch_scs);

      pdcch_params->nb_slots = 1;

      if ((scs_common==kHz120)&&(pdcch_scs==kHz60)) {
        pdcch_params->first_symbol = nr_ss_first_symb_idx_scs_120_60_mux2[ssb_idx&3];
        // Missing in pdcch_params sfn_C and n_C here and in else case
      }
      else {
        pdcch_params->first_symbol = ((ssb_idx&7)==4)?12 : ((ssb_idx&7)==4)?13 : nr_ss_first_symb_idx_scs_240_120_set1_mux2[ssb_idx&7]; //???
      }

    break;
Raymond Knopp's avatar
Raymond Knopp committed
323 324

    case NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE3:
325 326 327 328 329 330 331
      AssertFatal( (scs_common==kHz120)&&(pdcch_scs==kHz120),
      "Invalid scs_common/pdcch_scs combination %d/%d for Mux type 3\n", scs_common, pdcch_scs );
      AssertFatal(ss_idx==0, "Search space index %d reserved for scs_common/pdcch_scs combination %d/%d", ss_idx, scs_common, pdcch_scs);

      pdcch_params->first_symbol = nr_ss_first_symb_idx_scs_120_120_mux3[ssb_idx&3];

    break;
Raymond Knopp's avatar
Raymond Knopp committed
332 333 334 335 336 337 338 339 340

    default:
      AssertFatal(1==0, "Invalid SSB and coreset multiplexing pattern %d\n", pdcch_params->mux_pattern);
  }
  pdcch_params->config_type = NFAPI_NR_CSET_CONFIG_MIB_SIB1;
  pdcch_params->cr_mapping_type = NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED;
  pdcch_params->precoder_granularity = NFAPI_NR_CSET_SAME_AS_REG_BUNDLE;
  pdcch_params->reg_bundle_size = 6;
  pdcch_params->interleaver_size = 2;
341 342
  // set initial banwidth part to full bandwidth
  pdcch_params->n_RB_BWP = N_RB;
343 344


Raymond Knopp's avatar
Raymond Knopp committed
345 346
}

347
void nr_configure_dci_from_pdcch_config(nfapi_nr_dl_config_pdcch_parameters_rel15_t* pdcch_params,
Raymond Knopp's avatar
Raymond Knopp committed
348
                                            nfapi_nr_coreset_t* coreset,
349
                                            nfapi_nr_search_space_t* search_space,
Guy De Souza's avatar
Guy De Souza committed
350 351
                                            nfapi_nr_config_request_t cfg,
                                            uint16_t N_RB) {
352 353 354
/// coreset

  //ControlResourceSetId
Guy De Souza's avatar
Guy De Souza committed
355
  pdcch_params->config_type = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG;
356 357 358 359
  
  //frequencyDomainResources
  uint8_t count=0, start=0, start_set=0;
  uint64_t bitmap = coreset->frequency_domain_resources;
360

361 362
  for (int i=0; i<45; i++)
    if ((bitmap>>(44-i))&1) {
363
      count++;
364
      if (!start_set) {
365
        start = i;
366 367
        start_set = 1;
      }
368 369 370 371 372 373 374 375 376 377 378 379
    }
  pdcch_params->rb_offset = 6*start;
  pdcch_params->n_rb = 6*count;

  //duration
  pdcch_params->n_symb = coreset->duration;

  //cce-REG-MappingType
  pdcch_params->cr_mapping_type = coreset->cce_reg_mapping_type;
  if (pdcch_params->cr_mapping_type == NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED) {
    pdcch_params->reg_bundle_size = coreset->reg_bundle_size;
    pdcch_params->interleaver_size = coreset->interleaver_size;
380 381
  }
  else {
Guy De Souza's avatar
Guy De Souza committed
382 383
    pdcch_params->reg_bundle_size = 0;
    pdcch_params->interleaver_size = 0;
384
  }
Raymond Knopp's avatar
Raymond Knopp committed
385

386 387 388
  //shift index
  pdcch_params->shift_index = coreset->shift_index;

389 390 391 392 393 394 395 396
  //precoderGranularity
  pdcch_params->precoder_granularity = coreset->precoder_granularity;

  //TCI states
  // PDCCH params does not yet include information about TCI and QCL (needed for DCI 1.1 and 0.1)

  //pdcch-DMRS-ScramblingID
  pdcch_params->scrambling_id = coreset->dmrs_scrambling_id;
Raymond Knopp's avatar
Raymond Knopp committed
397
  
398 399 400

/// SearchSpace

401
  // first symbol
402 403
  //AssertFatal(pdcch_scs==kHz15, "PDCCH SCS above 15kHz not allowed if a symbol above 2 is monitored");
  for (int i=0; i<get_symbolsperslot(&cfg); i++)
404
    if ((search_space->monitoring_symbols_in_slot>>(31-i))&1) {
405
      pdcch_params->first_symbol=i;
406 407 408 409 410
      break;
    }

  //searchSpaceType
  pdcch_params->search_space_type = search_space->search_space_type;
411

Guy De Souza's avatar
Guy De Souza committed
412
  pdcch_params->n_RB_BWP = N_RB;
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
}

int nr_is_dci_opportunity(nfapi_nr_search_space_t search_space,
                                nfapi_nr_coreset_t coreset,
                                uint16_t frame,
                                uint16_t slot,
                                nfapi_nr_config_request_t cfg) {

  AssertFatal(search_space.coreset_id==coreset.coreset_id, "Invalid association of coreset(%d) and search space(%d)\n",
  search_space.search_space_id, coreset.coreset_id);

  uint8_t is_dci_opportunity=0;
  uint16_t Ks=search_space.slot_monitoring_periodicity;
  uint16_t Os=search_space.slot_monitoring_offset;
  uint8_t Ts=search_space.duration;

429
  if (((frame*get_spf(&cfg) + slot - Os)%Ks)<Ts)
430 431 432
    is_dci_opportunity=1;

  return is_dci_opportunity;
Raymond Knopp's avatar
Raymond Knopp committed
433
}
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458

int get_dlscs(nfapi_nr_config_request_t *cfg) {

  return(cfg->rf_config.dl_subcarrierspacing.value);
}


int get_ulscs(nfapi_nr_config_request_t *cfg) {

  return(cfg->rf_config.ul_subcarrierspacing.value);
} 

int get_spf(nfapi_nr_config_request_t *cfg) {

  int mu = cfg->rf_config.dl_subcarrierspacing.value;
  AssertFatal(mu>=0&&mu<4,"Illegal scs %d\n",mu);

  return(10 * (1<<mu));
} 

int to_absslot(nfapi_nr_config_request_t *cfg,int frame,int slot) {

  return(get_spf(cfg)*frame) + slot; 

}
459 460 461 462 463 464

int get_symbolsperslot(nfapi_nr_config_request_t *cfg) {

  return ((cfg->subframe_config.dl_cyclic_prefix_type.value==NFAPI_CP_EXTENDED)?12:14);

}
465

466

467
extern uint16_t nr_tbs_table[93];
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572

void nr_get_tbs(nfapi_nr_dl_config_dlsch_pdu *dlsch_pdu,
                nfapi_nr_dl_config_dci_dl_pdu dci_pdu) {

  LOG_D(MAC, "TBS calculation\n");

  nfapi_nr_dl_config_pdcch_parameters_rel15_t params_rel15 = dci_pdu.pdcch_params_rel15;
  nfapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_rel15 = &dlsch_pdu->dlsch_pdu_rel15;
  uint8_t rnti_type = params_rel15.rnti_type;
  uint8_t N_PRB_oh = ((rnti_type==NFAPI_NR_RNTI_SI)||(rnti_type==NFAPI_NR_RNTI_RA)||(rnti_type==NFAPI_NR_RNTI_P))? 0 : \
  (dlsch_rel15->x_overhead);
  uint8_t N_PRB_DMRS = (dlsch_rel15->dmrs_Type==1)?6:4; //This only works for antenna port 1000
  uint8_t N_sh_symb = dlsch_rel15->nb_symbols;
  uint8_t Imcs = dlsch_rel15->mcs_idx;
  uint16_t N_RE_prime = NR_NB_SC_PER_RB*N_sh_symb - N_PRB_DMRS - N_PRB_oh;
  LOG_D(MAC, "N_RE_prime %d for %d symbols %d DMRS per PRB and %d overhead\n", N_RE_prime, N_sh_symb, N_PRB_DMRS, N_PRB_oh);

  uint16_t N_RE, Ninfo, Ninfo_prime, C, TBS=0, R;
  uint8_t table_idx, Qm, n, scale;

  //uint8_t mcs_table = config.pdsch_config.mcs_table.value;
  //uint8_t ss_type = params_rel15.search_space_type;
  //uint8_t dci_format = params_rel15.dci_format;
  //get_table_idx(mcs_table, dci_format, rnti_type, ss_type);
  table_idx = 1;
  scale = ((table_idx==2)&&((Imcs==20)||(Imcs==26)))?11:10;
  
  N_RE = min(156, N_RE_prime)*dlsch_rel15->n_prb;
  R = nr_get_code_rate(Imcs, table_idx);
  Qm = nr_get_Qm(Imcs, table_idx);
  Ninfo = (N_RE*R*Qm*dlsch_rel15->nb_layers)>>scale;

  if (Ninfo <= 3824) {
    n = max(3, (log2(Ninfo)-6));
    Ninfo_prime = max(24, (Ninfo>>n)<<n);
    for (int i=0; i<93; i++)
      if (nr_tbs_table[i] >= Ninfo_prime) {
        TBS = nr_tbs_table[i];
        break;
      }
  }
  else {
    n = log2(Ninfo-24)-5;
    Ninfo_prime = max(3840, (ROUNDIDIV((Ninfo-24),(1<<n)))<<n);

    if (R<256) {
      C = CEILIDIV((Ninfo_prime+24),3816);
      TBS = (C<<3)*CEILIDIV((Ninfo_prime+24),(C<<3)) - 24;
    }
    else {
      if (Ninfo_prime>8424) {
        C = CEILIDIV((Ninfo_prime+24),8424);
        TBS = (C<<3)*CEILIDIV((Ninfo_prime+24),(C<<3)) - 24;
      }
      else
        TBS = ((CEILIDIV((Ninfo_prime+24),8))<<3) - 24;
    }    
  }

  dlsch_rel15->coding_rate = R;
  dlsch_rel15->modulation_order = Qm;
  dlsch_rel15->transport_block_size = TBS;
  dlsch_rel15->nb_mod_symbols = N_RE_prime*dlsch_rel15->n_prb*dlsch_rel15->nb_codewords;

  LOG_D(MAC, "TBS %d : N_RE %d  N_PRB_DMRS %d N_sh_symb %d N_PRB_oh %d Ninfo %d Ninfo_prime %d R %d Qm %d table %d scale %d nb_symbols %d\n",
  TBS, N_RE, N_PRB_DMRS, N_sh_symb, N_PRB_oh, Ninfo, Ninfo_prime, R, Qm, table_idx, scale, dlsch_rel15->nb_mod_symbols);
}

int extract_startSymbol(int startSymbolAndLength) {
  int tmp = startSymbolAndLength/14;
  int tmp2 = startSymbolAndLength%14;

  if (tmp > 0 && tmp < (14-tmp2)) return(tmp2);
  else                            return(13-tmp2);
}

int extract_length(int startSymbolAndLength) {
  int tmp = startSymbolAndLength/14;
  int tmp2 = startSymbolAndLength%14;

  if (tmp > 0 && tmp < (14-tmp2)) return(tmp);
  else                            return(15-tmp2);
}
 
void fill_initialBWPDLtimeDomainAllocaion(nfapi_nr_config_request_t *cfg,int time_domain_assignment,int *k0,int *mappingType,int *start_symbol,int *length) {
  AssertFatal(time_domain_assignment < cfg->pdsch_config.num_PDSCHTimeDomainResourceAllocations.value,"DL time_domain_assignment %d >= %d\n",
	      time_domain_assignment,cfg->pdsch_config.num_PDSCHTimeDomainResourceAllocations.value);
  *k0           = cfg->pdsch_config.PDSCHTimeDomainResourceAllocation_k0[time_domain_assignment].value;
  *mappingType = cfg->pdsch_config.PDSCHTimeDomainResourceAllocation_mappingType[time_domain_assignment].value;
  *start_symbol = extract_startSymbol(cfg->pdsch_config.PDSCHTimeDomainResourceAllocation_startSymbolAndLength[time_domain_assignment].value);
  *length       = extract_length(cfg->pdsch_config.PDSCHTimeDomainResourceAllocation_startSymbolAndLength[time_domain_assignment].value);

}



void fill_initialBWPULtimeDomainAllocaion(nfapi_nr_config_request_t *cfg,int time_domain_assignment,int *k2, int *mappingType, int *start_symbol,int *length) {
  AssertFatal(time_domain_assignment < cfg->pusch_config.num_PUSCHTimeDomainResourceAllocations.value,"UL time_domain_assignment %d >= %d\n",
	      time_domain_assignment,cfg->pusch_config.num_PUSCHTimeDomainResourceAllocations.value);

  *k2           = cfg->pusch_config.PUSCHTimeDomainResourceAllocation_k2[time_domain_assignment].value;
  *mappingType = cfg->pusch_config.PUSCHTimeDomainResourceAllocation_mappingType[time_domain_assignment].value;
  *start_symbol = extract_startSymbol(cfg->pusch_config.PUSCHTimeDomainResourceAllocation_startSymbolAndLength[time_domain_assignment].value);
  *length       = extract_length(cfg->pusch_config.PUSCHTimeDomainResourceAllocation_startSymbolAndLength[time_domain_assignment].value);
}