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

Guy De Souza's avatar
Guy De Souza committed
22 23 24 25
/*! \file PHY/NR_TRANSPORT/nr_dlsch_tools.c
* \brief Top-level routines for decoding  DLSCH transport channel from 38-214, V15.2.0 2018-06
* \author Guy De Souza
* \date 2018
26 27
* \version 0.1
* \company Eurecom
Guy De Souza's avatar
Guy De Souza committed
28
* \email: desouza@eurecom.fr
29
* \note
Raymond Knopp's avatar
Raymond Knopp committed
30

31 32 33 34
* \warning
*/

#include "nr_dlsch.h"
35
#include "../../../nfapi/oai_integration/vendor_ext.h"
36

Guy De Souza's avatar
Guy De Souza committed
37 38
extern void set_taus_seed(unsigned int seed_type);

39 40 41 42 43 44 45 46 47
uint8_t nr_pdsch_default_time_alloc_A_S_nCP[23] = {2,3,2,3,2,3,2,3,2,3,9,10,4,6,5,5,9,12,1,1,2,4,8};
uint8_t nr_pdsch_default_time_alloc_A_L_nCP[23] = {12,11,10,9,9,8,7,6,5,4,4,4,4,4,7,2,2,2,13,6,4,7,4};
uint8_t nr_pdsch_default_time_alloc_A_S_eCP[23] = {2,3,2,3,2,3,2,3,2,3,6,8,4,6,5,5,9,10,1,1,2,4,8};
uint8_t nr_pdsch_default_time_alloc_A_L_eCP[23] = {6,5,10,9,9,8,7,6,5,4,4,2,4,4,6,2,2,2,11,6,4,6,4};
uint8_t nr_pdsch_default_time_alloc_B_S[16] = {2,4,6,8,10,2,4,2,4,6,8,10,2,2,3,2};
uint8_t nr_pdsch_default_time_alloc_B_L[16] = {2,2,2,2,2,2,2,4,4,4,4,4,7,12,11,4};
uint8_t nr_pdsch_default_time_alloc_C_S[15] = {2,4,6,8,10,2,4,6,8,10,2,2,3,0,2};
uint8_t nr_pdsch_default_time_alloc_C_L[15] = {2,2,2,2,2,4,4,4,4,4,7,12,11,6,6};

Guy De Souza's avatar
Guy De Souza committed
48 49 50

  /// Time domain allocation routines

Raymond Knopp's avatar
Raymond Knopp committed
51
/*
52
void nr_get_time_domain_allocation_type(nfapi_nr_config_request_t config,
Guy De Souza's avatar
Guy De Souza committed
53 54
                                        nfapi_nr_dl_config_dci_dl_pdu dci_pdu,
                                        nfapi_nr_dl_config_dlsch_pdu *dlsch_pdu) {
55

Guy De Souza's avatar
Guy De Souza committed
56 57 58 59
  nfapi_nr_dl_config_pdcch_parameters_rel15_t params_rel15 = dci_pdu.pdcch_params_rel15;
  uint8_t *alloc_type = &dlsch_pdu->dlsch_pdu_rel15.time_allocation_type;
  uint8_t mux_pattern = params_rel15.mux_pattern;
  uint8_t alloc_list_flag = dlsch_pdu->dlsch_pdu_rel15.time_alloc_list_flag;
60

Guy De Souza's avatar
Guy De Souza committed
61
  switch(params_rel15.rnti_type) {
62 63

    case NFAPI_NR_RNTI_SI:
Guy De Souza's avatar
Guy De Souza committed
64
      AssertFatal(params_rel15.common_search_space_type == NFAPI_NR_COMMON_SEARCH_SPACE_TYPE_0,
65
      "Invalid common search space type %d for SI RNTI, expected %d\n",
Guy De Souza's avatar
Guy De Souza committed
66
      params_rel15.common_search_space_type, NFAPI_NR_COMMON_SEARCH_SPACE_TYPE_0);
67 68 69 70 71

      if (mux_pattern == NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1)
        AssertFatal(config.subframe_config.dl_cyclic_prefix_type.value == NFAPI_CP_NORMAL,
        "Invalid configuration CP extended for SI RNTI type 0 search space\n");

Guy De Souza's avatar
Guy De Souza committed
72
      *alloc_type = (mux_pattern == NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1)?NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_A :
73
                               (mux_pattern == NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2)?NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_B :
74
                               NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_C;
75 76 77 78
      break;

    case NFAPI_NR_RNTI_RA:
    case NFAPI_NR_RNTI_TC:
Raymond Knopp's avatar
Raymond Knopp committed
79 80 81
      //AssertFatal(dci_alloc.pdcch_params.common_search_space_type == NFAPI_NR_COMMON_SEARCH_SPACE_TYPE_1,
      //"Invalid common search space type %d for RNTI %d, expected %d\n",dci_alloc.pdcch_params.common_search_space_type,
      //NFAPI_NR_COMMON_SEARCH_SPACE_TYPE_1, dci_alloc.rnti_type);
Guy De Souza's avatar
Guy De Souza committed
82
      *alloc_type = (alloc_list_flag) ? NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_ALLOC_LIST : NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_A;
83 84 85 86 87 88 89
      break;

    case NFAPI_NR_RNTI_P:
      break;

    case NFAPI_NR_RNTI_C:
    case NFAPI_NR_RNTI_CS:
Guy De Souza's avatar
Guy De Souza committed
90 91
      if (params_rel15.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_COMMON)
        *alloc_type = (alloc_list_flag)? NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_ALLOC_LIST : NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_A;
92
      else
Guy De Souza's avatar
Guy De Souza committed
93
        *alloc_type = NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_ALLOC_LIST;
94 95 96 97 98 99

      break;

  }
}

Raymond Knopp's avatar
Raymond Knopp committed
100

Guy De Souza's avatar
Guy De Souza committed
101
uint16_t get_SLIV(uint8_t S, uint8_t L) {
102 103 104 105 106 107 108 109 110
  return ( (uint16_t)(((L-1)<=7)? (14*(L-1)+S) : (14*(15-L)+(13-S))) );
}

static inline uint8_t get_K0(uint8_t row_idx, uint8_t time_alloc_type) {
  return ( (time_alloc_type == NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_A)||
  (time_alloc_type == NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_C)? 0 :
  ((row_idx==6)||(row_idx==7)||(row_idx==15))? 1 : 0);
}

Raymond Knopp's avatar
Raymond Knopp committed
111
// ideally combine the calculation of L in the same function once the right struct is defined
112
uint8_t nr_get_S(uint8_t row_idx, uint8_t CP, uint8_t time_alloc_type, uint8_t dmrs_TypeA_Position) {
113

Guy De Souza's avatar
Guy De Souza committed
114 115
  uint8_t idx;
  //uint8_t S;
116 117 118

  switch(time_alloc_type) {
    case NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_A:
119
      idx = (row_idx>7)? (row_idx+6) : (((row_idx-1)<<1)-1+((dmrs_TypeA_Position==2)?0:1));
120 121 122 123
      return ((CP==NFAPI_CP_NORMAL)?nr_pdsch_default_time_alloc_A_S_nCP[idx] : nr_pdsch_default_time_alloc_A_S_eCP[idx]);
      break;

    case NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_B:
124
      idx = (row_idx<14)? (row_idx-1) : (row_idx == 14)? row_idx-1+((dmrs_TypeA_Position==2)?0:1) : 15;
125
      return (nr_pdsch_default_time_alloc_B_S[idx]);
126 127
      break;

128 129
    case NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_C:
      AssertFatal((row_idx!=6)&&(row_idx!=7)&&(row_idx<17), "Invalid row index %d in %s %s\n", row_idx, __FUNCTION__, __FILE__);
130
      idx = (row_idx<6)? (row_idx-1) : (row_idx<14)? (row_idx-3) : (row_idx == 14)? row_idx-3+((dmrs_TypeA_Position==2)?0:1) : (row_idx-2);
131 132 133 134 135
      break;

  default:
  AssertFatal(0, "Invalid Time domain allocation type %d in %s %s\n", time_alloc_type, __FUNCTION__, __FILE__);
  }
Guy De Souza's avatar
Guy De Souza committed
136
  return 0; // temp warning fix
137 138
}

Raymond Knopp's avatar
Raymond Knopp committed
139

140
void nr_check_time_alloc(uint8_t S, uint8_t L,nfapi_nr_dl_config_dlsch_pdu_rel15_t *rel15,nfapi_nr_config_request_t *cfg) {
141

142
  switch (cfg->subframe_config.dl_cyclic_prefix_type.value) {
143
    case NFAPI_CP_NORMAL:
144
      if (rel15->mapping_type == NFAPI_NR_PDSCH_MAPPING_TYPE_A) {
145 146 147
        AssertFatal(S<4, "Invalid value of S(%d) for mapping type A and normal CP\n", S);

        if (S==3)
148 149
          AssertFatal(rel15->dmrs_TypeA_Position == 3, "Invalid S %d for dmrs_TypeA_Position %d\n",
          S, rel15->dmrs_TypeA_Position);
150 151 152 153 154 155 156

        AssertFatal((L>2)&&(L<15), "Invalid L %d for mapping type A and normal CP\n", L);

        AssertFatal(((S+L)>2)&&((S+L)<15), "Invalid S+L %d for mapping type A and normal CP\n", S+L);
      }
      else {
        AssertFatal(S<13, "Invalid value of S(%d) for mapping type B and normal CP\n", S);
157

158
        AssertFatal((L>1)&&(L<8), "Invalid L %d for mapping type B and normal CP\n", L);
159

160 161 162 163 164
        AssertFatal(((S+L)>1)&&((S+L)<15), "Invalid S+L %d for mapping type B and normal CP\n", S+L);
      }
      break;

    case NFAPI_CP_EXTENDED:
165
      if (rel15->mapping_type == NFAPI_NR_PDSCH_MAPPING_TYPE_A) {
166 167 168
        AssertFatal(S<4, "Invalid value of S(%d) for mapping type A and extended CP\n", S);

        if (S==3)
169 170
          AssertFatal(rel15->dmrs_TypeA_Position == 3, "Invalid S %d for dmrs_TypeA_Position %d\n",
          S, rel15->dmrs_TypeA_Position);
171 172 173 174 175 176 177 178 179 180 181 182 183

        AssertFatal((L>2)&&(L<13), "Invalid L %d for mapping type A and extended CP\n", L);

        AssertFatal(((S+L)>2)&&((S+L)<13), "Invalid S+L %d for mapping type A and extended CP\n", S+L);
      }
      else {
        AssertFatal(S<11, "Invalid value of S(%d) for mapping type B and extended CP\n", S);

        AssertFatal((L>1)&&(L<7), "Invalid L %d for mapping type B and extended CP\n", L);

        AssertFatal(((S+L)>1)&&((S+L)<13), "Invalid S+L %d for mapping type B and extended CP\n", S+L);
      }
      break;
184 185 186 187
  }
}


Guy De Souza's avatar
Guy De Souza committed
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
  /// Frequency domain allocation routines

    // DL alloc type 0
static inline uint8_t get_RBG_size_P(uint16_t n_RB, uint8_t RBG_config) {
  if (RBG_config == NFAPI_NR_PDSCH_RBG_CONFIG_TYPE1)
    return ((n_RB<37)?2:(n_RB<73)?4:(n_RB<145)?8:16);
  else if (RBG_config == NFAPI_NR_PDSCH_RBG_CONFIG_TYPE2)
    return ((n_RB<37)?4:(n_RB<73)?8:(n_RB<145)?16:16);
  else
    AssertFatal(0, "Invalid RBG config type (%d)\n", RBG_config);
}

void nr_get_rbg_parms(NR_BWP_PARMS* bwp, uint8_t config_type) {
  nr_rbg_parms_t* rbg_parms = &bwp->rbg_parms;

  rbg_parms->P = get_RBG_size_P(bwp->N_RB, config_type);
  rbg_parms->start_size = rbg_parms->P - bwp->location%rbg_parms->P;
  rbg_parms->end_size = ((bwp->location + bwp->N_RB)%rbg_parms->P)? ((bwp->location + bwp->N_RB)%rbg_parms->P) : rbg_parms->P;
Guy De Souza's avatar
Guy De Souza committed
206
  rbg_parms->N_RBG = (uint8_t)ceil( (bwp->N_RB + (bwp->location%rbg_parms->P))/(float)rbg_parms->P);
Guy De Souza's avatar
Guy De Souza committed
207 208 209 210 211 212 213 214 215 216 217 218 219
  LOG_I(PHY, "RBG parameters for BWP %d location %d N_RB %d:\n", bwp->bwp_id, bwp->location, bwp->N_RB);
  LOG_I(PHY, "P %d\t start size %d\t endsize %d\t N_RBG %d\n", rbg_parms->P, rbg_parms->start_size, rbg_parms->end_size, rbg_parms->N_RBG);
}

void nr_get_rbg_list(uint32_t bitmap, uint8_t n_rbg, uint8_t* rbg_list) {
  uint8_t idx=0;
  for (int i=0; i<n_rbg; i++)
    if ((bitmap>>(n_rbg-i-1))&1)
      rbg_list[idx++]=i;
}

    // DL alloc type 1

Guy De Souza's avatar
Guy De Souza committed
220
uint16_t get_RIV(uint16_t rb_start, uint16_t L, uint16_t N_RB) {
Guy De Souza's avatar
Guy De Souza committed
221 222 223 224 225
  if ((L-1)<=(N_RB>>1))
    return (N_RB*(L-1)+rb_start);
  else
    return (N_RB*(N_RB-L+1) + (N_RB-1-rb_start));
}
Guy De Souza's avatar
Guy De Souza committed
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248

  /// PRB bundling routines

// Precoding granularity
static inline uint8_t nr_get_P_prime(uint8_t rnti_type, uint8_t dci_format, uint8_t prb_bundling_type) {
  if (dci_format == NFAPI_NR_DL_DCI_FORMAT_1_0)
    return (NFAPI_NR_PRG_GRANULARITY_2);
  else // NFAPI_NR_DL_DCI_FORMAT_1_1
    return ((prb_bundling_type)?0:2);// incomplete for 1_1
}

void nr_get_PRG_parms(NR_BWP_PARMS* bwp, NR_gNB_DCI_ALLOC_t dci_alloc, uint8_t prb_bundling_type) {
  nr_prg_parms_t* prg_parms = &bwp->prg_parms;

  prg_parms->P_prime = nr_get_P_prime(dci_alloc.pdcch_params.rnti_type, dci_alloc.pdcch_params.dci_format, prb_bundling_type);
  prg_parms->start_size = prg_parms->P_prime - bwp->location%prg_parms->P_prime;
  prg_parms->end_size = (bwp->location + bwp->N_RB)%prg_parms->P_prime;
  if (!prg_parms->end_size)
    prg_parms->end_size = prg_parms->P_prime;
  prg_parms->N_PRG = ceil((float)bwp->N_RB/prg_parms->P_prime);
  LOG_I(PHY, "PRG parameters for BWP %d location %d N_RB %d:\n", bwp->bwp_id, bwp->location, bwp->N_RB);
  LOG_I(PHY, "P_prime %d\t start size %d\t endsize %d\t N_PRG %d\n", prg_parms->P_prime, prg_parms->start_size, prg_parms->end_size, prg_parms->N_PRG);
}
Raymond Knopp's avatar
Raymond Knopp committed
249
*/
250 251 252 253 254 255 256

  /// Payload emulation
void nr_emulate_dlsch_payload(uint8_t* pdu, uint16_t size) {
  set_taus_seed(0);
  for (int i=0; i<size; i++)
    *(pdu+i) = (uint8_t)rand();
}
257 258

int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) {
259 260 261 262 263 264 265 266
 
   uint16_t i;
   int16_t first_free_index=-1;
 
   AssertFatal(gNB!=NULL,"gNB is null\n");
   for (i=0; i<NUMBER_OF_NR_DLSCH_MAX; i++) {
     AssertFatal(gNB->dlsch[i]!=NULL,"gNB->dlsch[%d] is null\n",i);
     AssertFatal(gNB->dlsch[i][0]!=NULL,"gNB->dlsch[%d][0] is null\n",i);
267 268 269
     //LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i,
	   //gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index);
     LOG_D(PHY,"searching for  harq_mask %x, rnti %x, gNB->dlsch[i][0]->rnti %x\n", gNB->dlsch[i][0]->harq_mask, rnti, gNB->dlsch[i][0]->rnti);
270 271
     if ((gNB->dlsch[i][0]->harq_mask >0) &&
	 (gNB->dlsch[i][0]->rnti==rnti))       return i;
272 273 274 275 276 277 278 279 280
     else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) {
     //printf("gNB->dlsch[i][0]->harq_mask = %d \n", gNB->dlsch[i][0]->harq_mask);;
     first_free_index=i;
     }

   }
   if (type == SEARCH_EXIST) {
     printf("type = %d \n", type);
     return -1;
281 282 283 284 285
   }
   if (first_free_index != -1)
     gNB->dlsch[first_free_index][0]->rnti = 0;
   return first_free_index;
   
286 287
}

288

289 290 291
void nr_fill_dlsch(PHY_VARS_gNB *gNB,
                   int frame,
                   int slot,
Raymond Knopp's avatar
Raymond Knopp committed
292
                   nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
293 294
                   uint8_t *sdu) {

Raymond Knopp's avatar
Raymond Knopp committed
295
  nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &pdsch_pdu->pdsch_pdu_rel15;
296 297 298 299
  if (NFAPI_MODE == NFAPI_MODE_PNF) {
    gNB->dlsch[0][0]->harq_mask = 1;
    gNB->dlsch[0][0]->rnti = 4660;
  }
300 301 302 303
  int dlsch_id = find_nr_dlsch(rel15->rnti,gNB,SEARCH_EXIST);
  AssertFatal( (dlsch_id>=0) && (dlsch_id<NUMBER_OF_NR_DLSCH_MAX),
              "illegal or no dlsch_id found!!! rnti %04x dlsch_id %d\n",rel15->rnti,dlsch_id);
  NR_gNB_DLSCH_t  *dlsch = gNB->dlsch[dlsch_id][0];
304
  NR_DL_gNB_HARQ_t *harq  = &dlsch->harq_process;
305
  /// DLSCH struct
306
  memcpy((void*)&harq->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu));
307
  gNB->num_pdsch_rnti[slot]++;
308
  AssertFatal(sdu!=NULL,"sdu is null\n");
309
  harq->pdu = sdu;
310 311 312 313


}