pre_processor.c 55.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * 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.0  (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
 */
21 22

/*! \file pre_processor.c
23
 * \brief eNB scheduler preprocessing fuction prior to scheduling
24
 * \author Navid Nikaein and Ankit Bhamri
25
 * \date 2013 - 2014
26
 * \email navid.nikaein@eurecom.fr
27
 * \version 1.0
28 29 30 31
 * @ingroup _mac

 */

32 33 34
#define _GNU_SOURCE
#include <stdlib.h>

35
#include "assertions.h"
36 37 38 39 40 41 42
#include "PHY/defs.h"
#include "PHY/extern.h"

#include "SCHED/defs.h"
#include "SCHED/extern.h"

#include "LAYER2/MAC/defs.h"
43
#include "LAYER2/MAC/proto.h"
44 45
#include "LAYER2/MAC/extern.h"
#include "UTIL/LOG/log.h"
46
#include "UTIL/LOG/vcd_signal_dumper.h"
47 48 49 50 51
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
52
#include "rlc.h"
53 54


55

56 57 58 59 60 61 62 63 64 65
#define DEBUG_eNB_SCHEDULER 1
#define DEBUG_HEADER_PARSING 1
//#define DEBUG_PACKET_TRACE 1

//#define ICIC 0

/*
  #ifndef USER_MODE
  #define msg debug_msg
  #endif
Raymond Knopp's avatar
 
Raymond Knopp committed
66
*/
67

68
/* this function checks that get_eNB_UE_stats returns
Cedric Roux's avatar
Cedric Roux committed
69
 * a non-NULL pointer for all the active CCs of an UE
70
 */
71
/*
72
int phy_stats_exist(module_id_t Mod_id, int rnti)
73 74
{
  int CC_id;
Cedric Roux's avatar
Cedric Roux committed
75 76
  int i;
  int UE_id          = find_UE_id(Mod_id, rnti);
77
  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
Cedric Roux's avatar
Cedric Roux committed
78 79 80 81 82 83 84 85 86 87 88 89
  if (UE_id == -1) {
    LOG_W(MAC, "[eNB %d] UE %x not found, should be there (in phy_stats_exist)\n",
	  Mod_id, rnti);
    return 0;
  }
  if (UE_list->numactiveCCs[UE_id] == 0) {
    LOG_W(MAC, "[eNB %d] UE %x has no active CC (in phy_stats_exist)\n",
	  Mod_id, rnti);
    return 0;
  }
  for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) {
    CC_id = UE_list->ordered_CCids[i][UE_id];
90 91
    if (mac_xface->get_eNB_UE_stats(Mod_id, CC_id, rnti) == NULL)
      return 0;
92
  }
93 94
  return 1;
}
95
*/
96

97
// This function stores the downlink buffer for all the logical channels
98 99
void store_dlsch_buffer (module_id_t Mod_id,
                         frame_t     frameP,
100 101
                         sub_frame_t subframeP)
{
Cedric Roux's avatar
Cedric Roux committed
102

Raymond Knopp's avatar
 
Raymond Knopp committed
103
  int                   UE_id,i;
104
  rnti_t                rnti;
105
  mac_rlc_status_resp_t rlc_status;
106
  UE_list_t             *UE_list = &RC.mac[Mod_id]->UE_list;
Raymond Knopp's avatar
 
Raymond Knopp committed
107 108
  UE_TEMPLATE           *UE_template;

109 110
  for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
    if (UE_list->active[UE_id] != TRUE) continue;
Raymond Knopp's avatar
 
Raymond Knopp committed
111 112

    UE_template = &UE_list->UE_template[UE_PCCID(Mod_id,UE_id)][UE_id];
113 114

    // clear logical channel interface variables
Raymond Knopp's avatar
 
Raymond Knopp committed
115 116
    UE_template->dl_buffer_total = 0;
    UE_template->dl_pdus_total = 0;
117 118

    for(i=0; i< MAX_NUM_LCID; i++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
119 120 121 122 123
      UE_template->dl_buffer_info[i]=0;
      UE_template->dl_pdus_in_buffer[i]=0;
      UE_template->dl_buffer_head_sdu_creation_time[i]=0;
      UE_template->dl_buffer_head_sdu_remaining_size_to_send[i]=0;
    }
124

Raymond Knopp's avatar
 
Raymond Knopp committed
125
    rnti = UE_RNTI(Mod_id,UE_id);
126 127 128

    for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels

129
      rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,subframeP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 );
Raymond Knopp's avatar
 
Raymond Knopp committed
130 131 132
      UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel
      UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer;
      UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ;
133 134
      UE_template->dl_buffer_head_sdu_creation_time_max = cmax(UE_template->dl_buffer_head_sdu_creation_time_max,
          rlc_status.head_sdu_creation_time );
Raymond Knopp's avatar
 
Raymond Knopp committed
135 136
      UE_template->dl_buffer_head_sdu_remaining_size_to_send[i] = rlc_status.head_sdu_remaining_size_to_send;
      UE_template->dl_buffer_head_sdu_is_segmented[i] = rlc_status.head_sdu_is_segmented;
137 138
      UE_template->dl_buffer_total += UE_template->dl_buffer_info[i];//storing the total dlsch buffer
      UE_template->dl_pdus_total   += UE_template->dl_pdus_in_buffer[i];
139

Cedric Roux's avatar
Cedric Roux committed
140
#ifdef DEBUG_eNB_SCHEDULER
141

Raymond Knopp's avatar
 
Raymond Knopp committed
142 143 144 145
      /* note for dl_buffer_head_sdu_remaining_size_to_send[i] :
       * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent
       */
      if (UE_template->dl_buffer_info[i]>0)
146 147
        LOG_D(MAC,
              "[eNB %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n",
148 149 150 151 152 153 154
              Mod_id, frameP, subframeP, UE_id,
              i, UE_template->dl_pdus_in_buffer[i],UE_template->dl_buffer_info[i],
              UE_template->dl_buffer_head_sdu_creation_time[i],
              UE_template->dl_buffer_head_sdu_remaining_size_to_send[i],
              UE_template->dl_buffer_head_sdu_is_segmented[i]
             );

Cedric Roux's avatar
Cedric Roux committed
155
#endif
156

Raymond Knopp's avatar
 
Raymond Knopp committed
157
    }
158

159
    //#ifdef DEBUG_eNB_SCHEDULER
Raymond Knopp's avatar
 
Raymond Knopp committed
160 161
    if ( UE_template->dl_buffer_total>0)
      LOG_D(MAC,"[eNB %d] Frame %d Subframe %d : RLC status for UE %d : total DL buffer size %d and total number of pdu %d \n",
162 163 164 165 166 167
            Mod_id, frameP, subframeP, UE_id,
            UE_template->dl_buffer_total,
            UE_template->dl_pdus_total
           );

    //#endif
168 169 170
  }
}

171

172
// This function returns the estimated number of RBs required by each UE for downlink scheduling
Raymond Knopp's avatar
 
Raymond Knopp committed
173
void assign_rbs_required (module_id_t Mod_id,
174 175 176 177 178
                          frame_t     frameP,
                          sub_frame_t subframe,
                          uint16_t    nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
                          int         min_rb_unit[MAX_NUM_CCs])
{
179

Raymond Knopp's avatar
 
Raymond Knopp committed
180
  uint16_t         TBS = 0;
181

Raymond Knopp's avatar
 
Raymond Knopp committed
182
  int              UE_id,n,i,j,CC_id,pCCid,tmp;
183
  UE_list_t        *UE_list = &RC.mac[Mod_id]->UE_list;
184
  eNB_UE_STATS     *eNB_UE_stats,*eNB_UE_stats_i,*eNB_UE_stats_j;
185
  int N_RB_DL;
186

187
  // clear rb allocations across all CC_id
188 189 190
  for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
    if (UE_list->active[UE_id] != TRUE) continue;

Raymond Knopp's avatar
 
Raymond Knopp committed
191
    pCCid = UE_PCCID(Mod_id,UE_id);
192

Raymond Knopp's avatar
 
Raymond Knopp committed
193
    //update CQI information across component carriers
194
    for (n=0; n<UE_list->numactiveCCs[UE_id]; n++) {
195

Raymond Knopp's avatar
 
Raymond Knopp committed
196
      CC_id = UE_list->ordered_CCids[n][UE_id];
197
      eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
198

199
      eNB_UE_stats->dlsch_mcs1=cqi_to_mcs[eNB_UE_stats->dl_cqi];
200

Raymond Knopp's avatar
 
Raymond Knopp committed
201
    }
202

Raymond Knopp's avatar
 
Raymond Knopp committed
203
    // provide the list of CCs sorted according to MCS
204
    for (i=0; i<UE_list->numactiveCCs[UE_id]; i++) {
205
      eNB_UE_stats_i = &UE_list->eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]][UE_id];
206
      for (j=i+1; j<UE_list->numactiveCCs[UE_id]; j++) {
207
        DevAssert( j < MAX_NUM_CCs );
208 209 210
	eNB_UE_stats_j = &UE_list->eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]][UE_id];
        if (eNB_UE_stats_j->dlsch_mcs1 >
            eNB_UE_stats_i->dlsch_mcs1) {
211 212 213 214
          tmp = UE_list->ordered_CCids[i][UE_id];
          UE_list->ordered_CCids[i][UE_id] = UE_list->ordered_CCids[j][UE_id];
          UE_list->ordered_CCids[j][UE_id] = tmp;
        }
215
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
216
    }
217 218

    if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total> 0) {
219
      LOG_D(MAC,"[preprocessor] assign RB for UE %d\n",UE_id);
220 221 222

      for (i=0; i<UE_list->numactiveCCs[UE_id]; i++) {
        CC_id = UE_list->ordered_CCids[i][UE_id];
223
	eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
224

225
        if (eNB_UE_stats->dlsch_mcs1==0) {
226 227 228 229
          nb_rbs_required[CC_id][UE_id] = 4;  // don't let the TBS get too small
        } else {
          nb_rbs_required[CC_id][UE_id] = min_rb_unit[CC_id];
        }
230

231
        TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]);
232 233 234

        LOG_D(MAC,"[preprocessor] start RB assignement for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n",
              UE_id, CC_id, UE_list->UE_template[pCCid][UE_id].dl_buffer_total,
235
              nb_rbs_required[CC_id][UE_id],eNB_UE_stats->dlsch_mcs1,TBS);
236

237 238
	N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);

239 240 241 242
        /* calculating required number of RBs for each UE */
        while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total)  {
          nb_rbs_required[CC_id][UE_id] += min_rb_unit[CC_id];

243
          if (nb_rbs_required[CC_id][UE_id] > N_RB_DL) {
244
            TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,N_RB_DL);
245
            nb_rbs_required[CC_id][UE_id] = N_RB_DL;
246 247 248
            break;
          }

249
          TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]);
250 251 252
        } // end of while

        LOG_D(MAC,"[eNB %d] Frame %d: UE %d on CC %d: RB unit %d,  nb_required RB %d (TBS %d, mcs %d)\n",
253
              Mod_id, frameP,UE_id, CC_id,  min_rb_unit[CC_id], nb_rbs_required[CC_id][UE_id], TBS, eNB_UE_stats->dlsch_mcs1);
Raymond Knopp's avatar
 
Raymond Knopp committed
254 255 256 257
      }
    }
  }
}
258 259


Raymond Knopp's avatar
 
Raymond Knopp committed
260
// This function scans all CC_ids for a particular UE to find the maximum round index of its HARQ processes
261

262 263
int maxround(module_id_t Mod_id,uint16_t rnti,int frame,sub_frame_t subframe,uint8_t ul_flag )
{
264

265
  uint8_t round,round_max=0,UE_id;
266
  int CC_id,harq_pid;
267
  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
268
  COMMON_channels_t *cc;
269

270 271
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {

272 273
    cc = &RC.mac[Mod_id]->common_channels[CC_id];

274
    UE_id = find_UE_id(Mod_id,rnti);
275 276 277 278
    if (cc->tdd_Config) harq_pid = ((frame*10)+subframe)%10;
    else harq_pid = ((frame*10)+subframe)&7;

    round    = UE_list->UE_sched_ctrl[UE_id].round[CC_id][harq_pid];
279
    if (round > round_max) {
Raymond Knopp's avatar
 
Raymond Knopp committed
280
      round_max = round;
281
    }
282 283
  }

284
  return round_max;
Raymond Knopp's avatar
 
Raymond Knopp committed
285
}
286

Raymond Knopp's avatar
 
Raymond Knopp committed
287
// This function scans all CC_ids for a particular UE to find the maximum DL CQI
288
// it returns -1 if the UE is not found in PHY layer (get_eNB_UE_stats gives NULL)
289 290
int maxcqi(module_id_t Mod_id,int32_t UE_id)
{
291

292
  eNB_UE_STATS *eNB_UE_stats = NULL;
293
  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
294
  int CC_id,n;
Raymond Knopp's avatar
 
Raymond Knopp committed
295
  int CQI = 0;
296

297
  for (n=0; n<UE_list->numactiveCCs[UE_id]; n++) {
298
    CC_id = UE_list->ordered_CCids[n][UE_id];
299
    eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
300

301 302
    if (eNB_UE_stats->dl_cqi > CQI) {
      CQI = eNB_UE_stats->dl_cqi;
303
    }
304
  }
305

Raymond Knopp's avatar
 
Raymond Knopp committed
306 307
  return(CQI);
}
308

309 310 311 312 313
struct sort_ue_dl_params {
  int Mod_idP;
  int frameP;
  int subframeP;
};
314

315 316 317
static int ue_dl_compare(const void *_a, const void *_b, void *_params)
{
  struct sort_ue_dl_params *params = _params;
318
  UE_list_t *UE_list = &RC.mac[params->Mod_idP]->UE_list;
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 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372

  int UE_id1 = *(const int *)_a;
  int UE_id2 = *(const int *)_b;

  int rnti1  = UE_RNTI(params->Mod_idP, UE_id1);
  int pCC_id1 = UE_PCCID(params->Mod_idP, UE_id1);
  int round1 = maxround(params->Mod_idP, rnti1, params->frameP, params->subframeP, 1);

  int rnti2  = UE_RNTI(params->Mod_idP, UE_id2);
  int pCC_id2 = UE_PCCID(params->Mod_idP, UE_id2);
  int round2 = maxround(params->Mod_idP, rnti2, params->frameP, params->subframeP, 1);

  int cqi1 = maxcqi(params->Mod_idP, UE_id1);
  int cqi2 = maxcqi(params->Mod_idP, UE_id2);

  if (round1 > round2) return -1;
  if (round1 < round2) return 1;

  if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] >
      UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2])
    return -1;
  if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] <
      UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2])
    return 1;

  if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max >
      UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max)
    return -1;
  if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max <
      UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max)
    return 1;

  if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total >
      UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total)
    return -1;
  if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total <
      UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total)
    return 1;

  if (cqi1 > cqi2) return -1;
  if (cqi1 < cqi2) return 1;

  return 0;
#if 0
  /* The above order derives from the following.  */
      if(round2 > round1) { // Check first if one of the UEs has an active HARQ process which needs service and swap order
        swap_UEs(UE_list,UE_id1,UE_id2,0);
      } else if (round2 == round1) {
        // RK->NN : I guess this is for fairness in the scheduling. This doesn't make sense unless all UEs have the same configuration of logical channels.  This should be done on the sum of all information that has to be sent.  And still it wouldn't ensure fairness.  It should be based on throughput seen by each UE or maybe using the head_sdu_creation_time, i.e. swap UEs if one is waiting longer for service.
        //  for(j=0;j<MAX_NUM_LCID;j++){
        //    if (eNB_mac_inst[Mod_id][pCC_id1].UE_template[UE_id1].dl_buffer_info[j] <
        //      eNB_mac_inst[Mod_id][pCC_id2].UE_template[UE_id2].dl_buffer_info[j]){

        // first check the buffer status for SRB1 and SRB2
373

374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
        if ( (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2]) <
             (UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2])   ) {
          swap_UEs(UE_list,UE_id1,UE_id2,0);
        } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max <
                   UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max   ) {
          swap_UEs(UE_list,UE_id1,UE_id2,0);
        } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total <
                   UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total   ) {
          swap_UEs(UE_list,UE_id1,UE_id2,0);
        } else if (cqi1 < cqi2) {
          swap_UEs(UE_list,UE_id1,UE_id2,0);
        }
      }
#endif
}
389

Raymond Knopp's avatar
 
Raymond Knopp committed
390
// This fuction sorts the UE in order their dlsch buffer and CQI
Raymond Knopp's avatar
 
Raymond Knopp committed
391
void sort_UEs (module_id_t Mod_idP,
392 393 394
               int         frameP,
               sub_frame_t subframeP)
{
395 396 397 398 399 400
  int               i;
  int               list[NUMBER_OF_UE_MAX];
  int               list_size = 0;
  int               rnti;
  struct sort_ue_dl_params params = { Mod_idP, frameP, subframeP };

401
  UE_list_t *UE_list = &RC.mac[Mod_idP]->UE_list;
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424

  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
    rnti = UE_RNTI(Mod_idP, i);
    if (rnti == NOT_A_RNTI)
      continue;
    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
      continue;
    list[list_size] = i;
    list_size++;
  }

  qsort_r(list, list_size, sizeof(int), ue_dl_compare, &params);

  if (list_size) {
    for (i = 0; i < list_size-1; i++)
      UE_list->next[list[i]] = list[i+1];
    UE_list->next[list[list_size-1]] = -1;
    UE_list->head = list[0];
  } else {
    UE_list->head = -1;
  }

#if 0
425 426


Raymond Knopp's avatar
 
Raymond Knopp committed
427 428 429
  int               UE_id1,UE_id2;
  int               pCC_id1,pCC_id2;
  int               cqi1,cqi2,round1,round2;
430
  int               i=0,ii=0;//,j=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
431
  rnti_t            rnti1,rnti2;
432

433
  UE_list_t *UE_list = &RC.mac[Mod_idP]->UE_list;
434

435
  for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
436

437
    for(ii=UE_list->next[i]; ii>=0; ii=UE_list->next[ii]) {
438

439 440
      UE_id1  = i;
      rnti1 = UE_RNTI(Mod_idP,UE_id1);
441 442
      if(rnti1 == NOT_A_RNTI)
	continue;
kaltenbe's avatar
kaltenbe committed
443 444
      if (UE_list->UE_sched_ctrl[UE_id1].ul_out_of_sync == 1)
	continue;
445 446 447
      pCC_id1 = UE_PCCID(Mod_idP,UE_id1);
      cqi1    = maxcqi(Mod_idP,UE_id1); //
      round1  = maxround(Mod_idP,rnti1,frameP,subframeP,0);
448

449 450
      UE_id2 = ii;
      rnti2 = UE_RNTI(Mod_idP,UE_id2);
451 452
      if(rnti2 == NOT_A_RNTI)
        continue;
kaltenbe's avatar
kaltenbe committed
453 454
      if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1)
	continue;
455
      cqi2    = maxcqi(Mod_idP,UE_id2);
456
      round2  = maxround(Mod_idP,rnti2,frameP,subframeP,0);  //mac_xface->get_ue_active_harq_pid(Mod_id,rnti2,subframe,&harq_pid2,&round2,0);
Raymond Knopp's avatar
 
Raymond Knopp committed
457
      pCC_id2 = UE_PCCID(Mod_idP,UE_id2);
458

459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
      if(round2 > round1) { // Check first if one of the UEs has an active HARQ process which needs service and swap order
        swap_UEs(UE_list,UE_id1,UE_id2,0);
      } else if (round2 == round1) {
        // RK->NN : I guess this is for fairness in the scheduling. This doesn't make sense unless all UEs have the same configuration of logical channels.  This should be done on the sum of all information that has to be sent.  And still it wouldn't ensure fairness.  It should be based on throughput seen by each UE or maybe using the head_sdu_creation_time, i.e. swap UEs if one is waiting longer for service.
        //  for(j=0;j<MAX_NUM_LCID;j++){
        //    if (eNB_mac_inst[Mod_id][pCC_id1].UE_template[UE_id1].dl_buffer_info[j] <
        //      eNB_mac_inst[Mod_id][pCC_id2].UE_template[UE_id2].dl_buffer_info[j]){

        // first check the buffer status for SRB1 and SRB2

        if ( (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2]) <
             (UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2])   ) {
          swap_UEs(UE_list,UE_id1,UE_id2,0);
        } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max <
                   UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max   ) {
          swap_UEs(UE_list,UE_id1,UE_id2,0);
        } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total <
                   UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total   ) {
          swap_UEs(UE_list,UE_id1,UE_id2,0);
        } else if (cqi1 < cqi2) {
          swap_UEs(UE_list,UE_id1,UE_id2,0);
        }
Raymond Knopp's avatar
 
Raymond Knopp committed
481 482
      }
    }
483
  }
484
#endif
485 486
}

487

Raymond Knopp's avatar
 
Raymond Knopp committed
488 489


490
// This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done
Raymond Knopp's avatar
 
Raymond Knopp committed
491
void dlsch_scheduler_pre_processor (module_id_t   Mod_id,
492 493 494 495 496
                                    frame_t       frameP,
                                    sub_frame_t   subframeP,
                                    int           N_RBG[MAX_NUM_CCs],
                                    int           *mbsfn_flag)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
497

498
  unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],harq_pid=0,round=0,total_ue_count;
Raymond Knopp's avatar
 
Raymond Knopp committed
499
  unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX];
500
  int                     UE_id, i; 
501
  uint16_t                ii,j;
Raymond Knopp's avatar
 
Raymond Knopp committed
502 503 504
  uint16_t                nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
  uint16_t                nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
  uint16_t                nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
505
  uint16_t                average_rbs_per_user[MAX_NUM_CCs] = {0};
506
  rnti_t             rnti;
Raymond Knopp's avatar
 
Raymond Knopp committed
507
  int                min_rb_unit[MAX_NUM_CCs];
508
  uint16_t r1=0;
509
  uint8_t CC_id;
510
  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
511

512
  int N_RB_DL;
513
  int transmission_mode = 0;
514 515
  UE_sched_ctrl *ue_sched_ctl;
  //  int rrc_status           = RRC_IDLE;
516
  COMMON_channels_t *cc;
517 518

#ifdef TM5
519
  int harq_pid1=0;
520 521 522 523 524 525 526 527
  int round1=0,round2=0;
  int UE_id2;
  uint16_t                i1,i2,i3;
  rnti_t             rnti1,rnti2;
  LTE_eNB_UE_stats  *eNB_UE_stats1 = NULL;
  LTE_eNB_UE_stats  *eNB_UE_stats2 = NULL;
  UE_sched_ctrl *ue_sched_ctl1,*ue_sched_ctl2;
#endif
528 529

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
530 531 532

    if (mbsfn_flag[CC_id]>0)  // If this CC is allocated for MBSFN skip it here
      continue;
533 534


Raymond Knopp's avatar
 
Raymond Knopp committed
535

536
    min_rb_unit[CC_id]=get_min_rb_unit(Mod_id,CC_id);
537

538 539 540
    for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
      if (UE_list->active[i] != TRUE) continue;

Raymond Knopp's avatar
 
Raymond Knopp committed
541
      UE_id = i;
542
      // Initialize scheduling information for all active UEs
543 544
      

545

546
      dlsch_scheduler_pre_processor_reset(Mod_id,
547 548
        UE_id,
        CC_id,
549 550
        frameP,
        subframeP,
551 552 553 554 555
        N_RBG[CC_id],
        nb_rbs_required,
        nb_rbs_required_remaining,
        rballoc_sub,
        MIMO_mode_indicator);
556

Raymond Knopp's avatar
 
Raymond Knopp committed
557
    }
558
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
559 560


561
  // Store the DLSCH buffer for each logical channel
562
  store_dlsch_buffer (Mod_id,frameP,subframeP);
563

Raymond Knopp's avatar
 
Raymond Knopp committed
564 565


566
  // Calculate the number of RBs required by each UE on the basis of logical channel's buffer
Raymond Knopp's avatar
 
Raymond Knopp committed
567
  assign_rbs_required (Mod_id,frameP,subframeP,nb_rbs_required,min_rb_unit);
568

Raymond Knopp's avatar
 
Raymond Knopp committed
569 570


571
  // Sorts the user on the basis of dlsch logical channel buffer and CQI
Raymond Knopp's avatar
 
Raymond Knopp committed
572 573 574
  sort_UEs (Mod_id,frameP,subframeP);


Raymond Knopp's avatar
 
Raymond Knopp committed
575

576
  total_ue_count =0;
577

Raymond Knopp's avatar
 
Raymond Knopp committed
578
  // loop over all active UEs
579
  for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
580
    rnti = UE_RNTI(Mod_id,i);
581

582
    if(rnti == NOT_A_RNTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
583
      continue;
kaltenbe's avatar
kaltenbe committed
584 585
    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
      continue;
586
    UE_id = i;
587

588
    for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
589
      CC_id = UE_list->ordered_CCids[ii][UE_id];
590
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
591 592 593 594
      cc=&RC.mac[Mod_id]->common_channels[ii];
      if (cc->tdd_Config) harq_pid = ((frameP*10)+subframeP)%10;
      else harq_pid = ((frameP*10)+subframeP)&7;
      round    = ue_sched_ctl->round[CC_id][harq_pid];
595

Raymond Knopp's avatar
 
Raymond Knopp committed
596 597
      average_rbs_per_user[CC_id]=0;

598

599
      if(round>0) {
600
        nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
601
      }
602

Raymond Knopp's avatar
 
Raymond Knopp committed
603 604
      //nb_rbs_required_remaining[UE_id] = nb_rbs_required[UE_id];
      if (nb_rbs_required[CC_id][UE_id] > 0) {
605
        total_ue_count = total_ue_count + 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
606
      }
607 608


609
      // hypothetical assignment
610 611 612 613 614 615 616 617 618
      /*
       * If schedule is enabled and if the priority of the UEs is modified
       * The average rbs per logical channel per user will depend on the level of
       * priority. Concerning the hypothetical assignement, we should assign more
       * rbs to prioritized users. Maybe, we can do a mapping between the
       * average rbs per user and the level of priority or multiply the average rbs
       * per user by a coefficient which represents the degree of priority.
       */

619 620
      N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);

621
      if (total_ue_count == 0) {
622
        average_rbs_per_user[CC_id] = 0;
623 624
      } else if( (min_rb_unit[CC_id] * total_ue_count) <= (N_RB_DL) ) {
        average_rbs_per_user[CC_id] = (uint16_t) floor(N_RB_DL/total_ue_count);
625
      } else {
626
        average_rbs_per_user[CC_id] = min_rb_unit[CC_id]; // consider the total number of use that can be scheduled UE
627
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
628 629
    }
  }
630

631 632
  // note: nb_rbs_required is assigned according to total_buffer_dl
  // extend nb_rbs_required to capture per LCID RB required
633
  for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
634
    rnti = UE_RNTI(Mod_id,i);
635

636 637 638 639 640
    if(rnti == NOT_A_RNTI)
      continue;
    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
      continue;

641
    for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) {
642
      CC_id = UE_list->ordered_CCids[ii][i];
Cedric Roux's avatar
Cedric Roux committed
643
      ue_sched_ctl = &UE_list->UE_sched_ctrl[i];
644
      round    = ue_sched_ctl->round[CC_id][harq_pid];
645

Cedric Roux's avatar
Cedric Roux committed
646 647 648
      // control channel or retransmission
      /* TODO: do we have to check for retransmission? */
      if (mac_eNB_get_rrc_status(Mod_id,rnti) < RRC_RECONFIGURED || round > 0) {
649
        nb_rbs_required_remaining_1[CC_id][i] = nb_rbs_required[CC_id][i];
650
      } else {
651 652
        nb_rbs_required_remaining_1[CC_id][i] = cmin(average_rbs_per_user[CC_id],nb_rbs_required[CC_id][i]);

653
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
654
    }
655
  }
656

657
  //Allocation to UEs is done in 2 rounds,
658 659
  // 1st stage: average number of RBs allocated to each UE
  // 2nd stage: remaining RBs are allocated to high priority UEs
660 661 662 663 664 665
  for(r1=0; r1<2; r1++) {

    for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
      for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) {
        CC_id = UE_list->ordered_CCids[ii][i];

666
        if(r1 == 0) {
667
          nb_rbs_required_remaining[CC_id][i] = nb_rbs_required_remaining_1[CC_id][i];
668
        } else { // rb required based only on the buffer - rb allloctaed in the 1st round + extra reaming rb form the 1st round
669
          nb_rbs_required_remaining[CC_id][i] = nb_rbs_required[CC_id][i]-nb_rbs_required_remaining_1[CC_id][i]+nb_rbs_required_remaining[CC_id][i];
Cedric Roux's avatar
Cedric Roux committed
670
if (nb_rbs_required_remaining[CC_id][i]<0) abort();
671
        }
672 673 674 675 676 677 678

        if (nb_rbs_required[CC_id][i]> 0 )
          LOG_D(MAC,"round %d : nb_rbs_required_remaining[%d][%d]= %d (remaining_1 %d, required %d,  pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n",
                r1, CC_id, i,
                nb_rbs_required_remaining[CC_id][i],
                nb_rbs_required_remaining_1[CC_id][i],
                nb_rbs_required[CC_id][i],
679
                UE_list->UE_sched_ctrl[i].pre_nb_available_rbs[CC_id],
680 681 682
                N_RBG[CC_id],
                min_rb_unit[CC_id]);

683
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
684
    }
685

686
    if (total_ue_count > 0 ) {
687 688 689 690 691
      for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
        UE_id = i;

        for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
          CC_id = UE_list->ordered_CCids[ii][UE_id];
692
	  ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
693
	  round    = ue_sched_ctl->round[CC_id][harq_pid];
694 695 696 697

          rnti = UE_RNTI(Mod_id,UE_id);

          // LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti );
698
          if(rnti == NOT_A_RNTI)
699
            continue;
kaltenbe's avatar
kaltenbe committed
700 701
	  if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1)
	    continue;
702

703
          transmission_mode = get_tmode(Mod_id,CC_id,UE_id);
704 705
	  //          mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0);
          //rrc_status = mac_eNB_get_rrc_status(Mod_id,rnti);
706 707 708 709 710 711 712 713 714 715 716 717
          /* 1st allocate for the retx */

          // retransmission in data channels
          // control channel in the 1st transmission
          // data channel for all TM
          LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n ");
          dlsch_scheduler_pre_processor_allocate (Mod_id,
                                                  UE_id,
                                                  CC_id,
                                                  N_RBG[CC_id],
                                                  transmission_mode,
                                                  min_rb_unit[CC_id],
718
                                                  to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth),
719 720 721 722 723
                                                  nb_rbs_required,
                                                  nb_rbs_required_remaining,
                                                  rballoc_sub,
                                                  MIMO_mode_indicator);

724
#ifdef TM5
725 726 727 728

          // data chanel TM5: to be revisted
          if ((round == 0 )  &&
              (transmission_mode == 5)  &&
729
              (ue_sched_ctl->dl_pow_off[CC_id] != 1)) {
730 731 732

            for(j=0; j<N_RBG[CC_id]; j+=2) {

733 734
              if( (((j == (N_RBG[CC_id]-1))&& (rballoc_sub[CC_id][j] == 0) && (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 0))  ||
                   ((j < (N_RBG[CC_id]-1)) && (rballoc_sub[CC_id][j+1] == 0) && (ue_sched_ctl->rballoc_sub_UE[CC_id][j+1] == 0)) ) &&
735 736 737 738 739 740
                  (nb_rbs_required_remaining[CC_id][UE_id]>0)) {

                for (ii = UE_list->next[i+1]; ii >=0; ii=UE_list->next[ii]) {

                  UE_id2 = ii;
                  rnti2 = UE_RNTI(Mod_id,UE_id2);
741 742
		  ue_sched_ctl2 = &UE_list->UE_sched_ctrl[UE_id2];
		  round2    = ue_sched_ctl2->round[CC_id];
743
                  if(rnti2 == NOT_A_RNTI)
744
                    continue;
kaltenbe's avatar
kaltenbe committed
745 746
		  if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1)
		    continue;
747

748
                  eNB_UE_stats2 = UE_list->eNB_UE_stats[CC_id][UE_id2];
749
                  //mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti2,frameP,subframeP,&harq_pid2,&round2,0);
750

751
                  if ((mac_eNB_get_rrc_status(Mod_id,rnti2) >= RRC_RECONFIGURED) &&
752
                      (round2==0) &&
753
                      (get_tmode(Mod_id,CC_id,UE_id2)==5) &&
754
                      (ue_sched_ctl->dl_pow_off[CC_id] != 1)) {
755

756 757
                    if( (((j == (N_RBG[CC_id]-1)) && (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 0)) ||
                         ((j < (N_RBG[CC_id]-1)) && (ue_sched_ctl->rballoc_sub_UE[CC_id][j+1] == 0))  ) &&
758 759 760 761 762
                        (nb_rbs_required_remaining[CC_id][UE_id2]>0)) {

                      if((((eNB_UE_stats2->DL_pmi_single^eNB_UE_stats1->DL_pmi_single)<<(14-j))&0xc000)== 0x4000) { //MU-MIMO only for 25 RBs configuration

                        rballoc_sub[CC_id][j] = 1;
763 764
                        ue_sched_ctl->rballoc_sub_UE[CC_id][j] = 1;
                        ue_sched_ctl2->rballoc_sub_UE[CC_id][j] = 1;
765 766 767 768
                        MIMO_mode_indicator[CC_id][j] = 0;

                        if (j< N_RBG[CC_id]-1) {
                          rballoc_sub[CC_id][j+1] = 1;
769 770
                          ue_sched_ctl->rballoc_sub_UE[CC_id][j+1] = 1;
                          ue_sched_ctl2->rballoc_sub_UE[CC_id][j+1] = 1;
771 772 773
                          MIMO_mode_indicator[CC_id][j+1] = 0;
                        }

774 775
                        ue_sched_ctl->dl_pow_off[CC_id] = 0;
                        ue_sched_ctl2->dl_pow_off[CC_id] = 0;
776 777 778


                        if ((j == N_RBG[CC_id]-1) &&
779 780
                            ((N_RB_DL == 25) ||
                             (N_RB_DL == 50))) {
781
			  
782
                          nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit[CC_id]+1;
783
                          ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit[CC_id]-1;
784
                          nb_rbs_required_remaining[CC_id][UE_id2] = nb_rbs_required_remaining[CC_id][UE_id2] - min_rb_unit[CC_id]+1;
785
                          ue_sched_ctl2->pre_nb_available_rbs[CC_id] = ue_sched_ctl2->pre_nb_available_rbs[CC_id] + min_rb_unit[CC_id]-1;
786
                        } else {
787 788
                          
			  nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - 4;
789
                          ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + 4;
790
                          nb_rbs_required_remaining[CC_id][UE_id2] = nb_rbs_required_remaining[CC_id][UE_id2] - 4;
791
                          ue_sched_ctl2->pre_nb_available_rbs[CC_id] = ue_sched_ctl2->pre_nb_available_rbs[CC_id] + 4;
792 793 794 795 796 797 798 799 800 801 802 803 804
                        }

                        break;
                      }
                    }
                  }
                }
              }
            }
          }

#endif
        }
Raymond Knopp's avatar
 
Raymond Knopp committed
805
      }
806
    } // total_ue_count
807
  } // end of for for r1 and r2
808 809 810

#ifdef TM5

Raymond Knopp's avatar
 
Raymond Knopp committed
811
  // This has to be revisited!!!!
812
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
813 814 815
    i1=0;
    i2=0;
    i3=0;
816 817

    for (j=0; j<N_RBG[CC_id]; j++) {
818
      if(MIMO_mode_indicator[CC_id][j] == 2) {
819
        i1 = i1+1;
820
      } else if(MIMO_mode_indicator[CC_id][j] == 1) {
821
        i2 = i2+1;
822
      } else if(MIMO_mode_indicator[CC_id][j] == 0) {
823
        i3 = i3+1;
824
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
825
    }
826

827
    if((i1 < N_RBG[CC_id]) && (i2>0) && (i3==0)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
828
      PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions + 1;
829
    }
830

831
    if(i3 == N_RBG[CC_id] && i1==0 && i2==0) {
Raymond Knopp's avatar
 
Raymond Knopp committed
832
      PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions + 1;
833
    }
834

835
    if((i1 < N_RBG[CC_id]) && (i3 > 0)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
836
      PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions + 1;
837
    }
838

Raymond Knopp's avatar
 
Raymond Knopp committed
839
    PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions + 1;
840

841 842
  }

843 844 845
#endif

  for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
846
    UE_id = i;
847
    ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
848 849

    for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
850
      CC_id = UE_list->ordered_CCids[ii][UE_id];
851
      //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id];
852

853
      if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0 ) {
854
        LOG_D(MAC,"******************DL Scheduling Information for UE%d ************************\n",UE_id);
855
        LOG_D(MAC,"dl power offset UE%d = %d \n",UE_id,ue_sched_ctl->dl_pow_off[CC_id]);
856 857 858 859
        LOG_D(MAC,"***********RB Alloc for every subband for UE%d ***********\n",UE_id);

        for(j=0; j<N_RBG[CC_id]; j++) {
          //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[i] = rballoc_sub_UE[CC_id][UE_id][i];
860
          LOG_D(MAC,"RB Alloc for UE%d and Subband%d = %d\n",UE_id,j,ue_sched_ctl->rballoc_sub_UE[CC_id][j]);
861 862 863
        }

        //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id];
864
        LOG_D(MAC,"Total RBs allocated for UE%d = %d\n",UE_id,ue_sched_ctl->pre_nb_available_rbs[CC_id]);
865
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
866
    }
867 868 869
  }
}

Cedric Roux's avatar
Cedric Roux committed
870
#define SF0_LIMIT 1
871

872
void dlsch_scheduler_pre_processor_reset (int module_idP,
873 874 875 876 877 878 879 880 881 882
					  int UE_id,
					  uint8_t  CC_id,
					  int frameP,
					  int subframeP,					  
					  int N_RBG,
					  uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
					  uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
					  unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],
					  unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX])
  
883
{
884
  int i,j;
885
  UE_list_t *UE_list=&RC.mac[module_idP]->UE_list;
886 887
  UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
  rnti_t rnti = UE_RNTI(module_idP,UE_id);
888

889
  uint8_t *vrb_map = RC.mac[module_idP]->common_channels[CC_id].vrb_map;
890
  int N_RB_DL = to_prb(RC.mac[module_idP]->common_channels[CC_id].mib->message.dl_Bandwidth);
891
  int RBGsize = N_RB_DL/N_RBG,RBGsize_last;
Cedric Roux's avatar
Cedric Roux committed
892 893
#ifdef SF0_LIMIT
  int sf0_upper=-1,sf0_lower=-1;
894
#endif
895 896


897
  LOG_D(MAC,"Running preprocessor for UE %d (%x)\n",UE_id,rnti);
898
  // initialize harq_pid and round
899

900 901 902
  /*
  eNB_UE_stats *eNB_UE_stats;

903 904 905
  if (eNB_UE_stats == NULL)
    return;

906
  
907 908 909 910
  mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,
				    frameP,subframeP,
				    &ue_sched_ctl->harq_pid[CC_id],
				    &ue_sched_ctl->round[CC_id],
911
				    openair_harq_DL);
912 913
  

914
  if (ue_sched_ctl->ta_timer == 0) {
915

916 917 918
    // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ...

    ue_sched_ctl->ta_timer = 20;  // wait 20 subframes before taking TA measurement from PHY
919
    switch (N_RB_DL) {
920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940
    case 6:
      ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update;
      break;
      
    case 15:
      ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/2;
      break;
      
    case 25:
      ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/4;
      break;
      
    case 50:
      ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/8;
      break;
      
    case 75:
      ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/12;
      break;
      
    case 100:
941
	ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/16;
942 943 944 945 946 947 948 949 950
      break;
    }
    // clear the update in case PHY does not have a new measurement after timer expiry
    eNB_UE_stats->timing_advance_update =  0;
  }
  else {
    ue_sched_ctl->ta_timer--;
    ue_sched_ctl->ta_update =0; // don't trigger a timing advance command
  }
951 952
  

953 954 955
  if (UE_id==0) {
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_TIMING_ADVANCE,ue_sched_ctl->ta_update);
  }
956 957
  */

958
  nb_rbs_required[CC_id][UE_id]=0;
959 960
  ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0;
  ue_sched_ctl->dl_pow_off[CC_id] = 2;
961
  nb_rbs_required_remaining[CC_id][UE_id] = 0;
962 963
  
  switch (N_RB_DL) {
Cedric Roux's avatar
Cedric Roux committed
964 965 966 967 968 969
  case 6:   RBGsize = 1; RBGsize_last = 1; break;
  case 15:  RBGsize = 2; RBGsize_last = 1; break;
  case 25:  RBGsize = 2; RBGsize_last = 1; break;
  case 50:  RBGsize = 3; RBGsize_last = 2; break;
  case 75:  RBGsize = 4; RBGsize_last = 3; break;
  case 100: RBGsize = 4; RBGsize_last = 4; break;
970
  default: AssertFatal(1==0,"unsupported RBs (%d)\n", N_RB_DL);
Cedric Roux's avatar
Cedric Roux committed
971
  }
972
  
Cedric Roux's avatar
Cedric Roux committed
973
#ifdef SF0_LIMIT
974 975
  switch (N_RBG) {
  case 6:
Cedric Roux's avatar
Cedric Roux committed
976 977
    sf0_lower=0;
    sf0_upper=5;
978 979
    break;
  case 8:
Cedric Roux's avatar
Cedric Roux committed
980 981
    sf0_lower=2;
    sf0_upper=5;
982 983
    break;
  case 13:
Cedric Roux's avatar
Cedric Roux committed
984 985
    sf0_lower=4;
    sf0_upper=7;
986 987
    break;
  case 17:
Cedric Roux's avatar
Cedric Roux committed
988 989
    sf0_lower=7;
    sf0_upper=9;
990 991
    break;
  case 25:
Cedric Roux's avatar
Cedric Roux committed
992 993
    sf0_lower=11;
    sf0_upper=13;
994
    break;
995
  default: AssertFatal(1==0,"unsupported RBs (%d)\n", N_RB_DL);
996 997
  }
#endif
998
  // Initialize Subbands according to VRB map
999
  for (i=0; i<N_RBG; i++) {
Cedric Roux's avatar
Cedric Roux committed
1000 1001
    int rb_size = i==N_RBG-1 ? RBGsize_last : RBGsize;

1002
    ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0;
1003
    rballoc_sub[CC_id][i] = 0;
Cedric Roux's avatar
Cedric Roux committed
1004 1005 1006 1007 1008 1009 1010 1011
#ifdef SF0_LIMIT
    // for avoiding 6+ PRBs around DC in subframe 0 (avoid excessive errors)
    /* TODO: make it proper - allocate those RBs, do not "protect" them, but
     * compute number of available REs and limit MCS according to the
     * TBS table 36.213 7.1.7.2.1-1 (can be done after pre-processor)
     */
    if (subframeP==0 &&
	i >= sf0_lower && i <= sf0_upper)
1012 1013 1014
      rballoc_sub[CC_id][i]=1;
#endif
    // for SI-RNTI,RA-RNTI and P-RNTI allocations
Cedric Roux's avatar
Cedric Roux committed
1015 1016
    for (j = 0; j < rb_size; j++) {
      if (vrb_map[j+(i*RBGsize)] != 0)  {
1017
	rballoc_sub[CC_id][i] = 1;
1018
	LOG_D(MAC,"Frame %d, subframe %d : vrb %d allocated\n",frameP,subframeP,j+(i*RBGsize));
1019 1020 1021 1022
	break;
      }
    }
    LOG_D(MAC,"Frame %d Subframe %d CC_id %d RBG %i : rb_alloc %d\n",frameP,subframeP,CC_id,i,rballoc_sub[CC_id][i]);
1023
    MIMO_mode_indicator[CC_id][i] = 2;
1024 1025 1026 1027 1028
  }
}


void dlsch_scheduler_pre_processor_allocate (module_id_t   Mod_id,
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
    int           UE_id,
    uint8_t       CC_id,
    int           N_RBG,
    int           transmission_mode,
    int           min_rb_unit,
    uint8_t       N_RB_DL,
    uint16_t      nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
    uint16_t      nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
    unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],
    unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX])
{

1041
  int i;
1042
  UE_list_t *UE_list=&RC.mac[Mod_id]->UE_list;
1043
  UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
1044 1045 1046 1047

  for(i=0; i<N_RBG; i++) {

    if((rballoc_sub[CC_id][i] == 0)           &&
1048
        (ue_sched_ctl->rballoc_sub_UE[CC_id][i] == 0) &&
1049
        (nb_rbs_required_remaining[CC_id][UE_id]>0)   &&
1050
        (ue_sched_ctl->pre_nb_available_rbs[CC_id] < nb_rbs_required[CC_id][UE_id])) {
1051

1052
      // if this UE is not scheduled for TM5
1053
      if (ue_sched_ctl->dl_pow_off[CC_id] != 0 )  {
1054

1055
	if ((i == N_RBG-1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) {
Cedric Roux's avatar
Cedric Roux committed
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065
	  if (nb_rbs_required_remaining[CC_id][UE_id] >=  min_rb_unit-1){
            rballoc_sub[CC_id][i] = 1;
            ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
            MIMO_mode_indicator[CC_id][i] = 1;
            if (transmission_mode == 5 ) {
              ue_sched_ctl->dl_pow_off[CC_id] = 1;
            }
            nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit+1;
            ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1;
          }
1066
        } else {
1067 1068
	  if (nb_rbs_required_remaining[CC_id][UE_id] >=  min_rb_unit){
	    rballoc_sub[CC_id][i] = 1;
1069
	    ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
1070 1071
	    MIMO_mode_indicator[CC_id][i] = 1;
	    if (transmission_mode == 5 ) {
1072
	      ue_sched_ctl->dl_pow_off[CC_id] = 1;
1073 1074
	    }
	    nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit;
1075
	    ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit;
1076 1077
	  }
	}
1078 1079
      } // dl_pow_off[CC_id][UE_id] ! = 0
    }
1080
  }
1081 1082 1083
}


1084
/// ULSCH PRE_PROCESSOR
1085

1086

1087
void ulsch_scheduler_pre_processor(module_id_t module_idP,
1088 1089
                                   int frameP,
                                   sub_frame_t subframeP,
1090
                                   uint16_t *first_rb)
1091
{
1092 1093 1094

  int16_t            i;
  uint16_t           UE_id,n,r;
1095
  uint8_t            CC_id, harq_pid;
1096 1097
  uint16_t           nb_allocated_rbs[MAX_NUM_CCs][NUMBER_OF_UE_MAX],total_allocated_rbs[MAX_NUM_CCs],average_rbs_per_user[MAX_NUM_CCs];
  int16_t            total_remaining_rbs[MAX_NUM_CCs];
1098 1099 1100 1101 1102
  uint16_t           max_num_ue_to_be_scheduled = 0;
  uint16_t           total_ue_count             = 0;
  rnti_t             rnti                       = -1;
  UE_list_t          *UE_list                   = &RC.mac[module_idP]->UE_list;
  UE_TEMPLATE        *UE_template               = 0;
1103 1104
  int                N_RB_DL;
  int                N_RB_UL;
1105
  LOG_D(MAC,"In ulsch_preprocessor: assign max mcs min rb\n");
1106 1107
  // maximize MCS and then allocate required RB according to the buffer occupancy with the limit of max available UL RB
  assign_max_mcs_min_rb(module_idP,frameP, subframeP, first_rb);
1108

1109
  LOG_D(MAC,"In ulsch_preprocessor: sort ue \n");
1110
  // sort ues
1111 1112
  sort_ue_ul (module_idP,frameP, subframeP);

1113

1114 1115
  // we need to distribute RBs among UEs
  // step1:  reset the vars
1116
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1117 1118 1119 1120 1121
    N_RB_DL                     = to_prb(RC.mac[module_idP]->common_channels[CC_id].mib->message.dl_Bandwidth);
    N_RB_UL                     = to_prb(RC.mac[module_idP]->common_channels[CC_id].ul_Bandwidth);
    total_allocated_rbs[CC_id]  = 0;
    total_remaining_rbs[CC_id]  = 0;
    average_rbs_per_user[CC_id] = 0;
1122 1123

    for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) {
1124 1125 1126 1127
      nb_allocated_rbs[CC_id][i]=0;
    }
  }

1128
  LOG_D(MAC,"In ulsch_preprocessor: step2 \n");
1129 1130 1131
  // step 2: calculate the average rb per UE
  total_ue_count =0;
  max_num_ue_to_be_scheduled=0;
1132 1133 1134 1135 1136

  for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) {

    rnti = UE_RNTI(module_idP,i);

1137
    if (rnti==NOT_A_RNTI)
1138 1139
      continue;

kaltenbe's avatar
kaltenbe committed
1140 1141 1142
    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
      continue;

1143

1144
    UE_id = i;
1145

1146
    LOG_D(MAC,"In ulsch_preprocessor: handling UE %d/%x\n",UE_id,rnti);
1147
    for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
1148 1149
      // This is the actual CC_id in the list
      CC_id = UE_list->ordered_ULCCids[n][UE_id];
1150
      LOG_D(MAC,"In ulsch_preprocessor: handling UE %d/%x CCid %d\n",UE_id,rnti,CC_id);
1151 1152
      UE_template = &UE_list->UE_template[CC_id][UE_id];
      average_rbs_per_user[CC_id]=0;
1153

1154
      if (UE_template->pre_allocated_nb_rb_ul > 0) {
1155
        total_ue_count+=1;
1156
      }
1157 1158
      /*
      if((mac_xface->get_nCCE_max(module_idP,CC_id,3,subframeP) - nCCE_to_be_used[CC_id])  > (1<<aggregation)) {
1159 1160
        nCCE_to_be_used[CC_id] = nCCE_to_be_used[CC_id] + (1<<aggregation);
        max_num_ue_to_be_scheduled+=1;
1161 1162 1163
	}*/

      max_num_ue_to_be_scheduled+=1;
1164

1165
      if (total_ue_count == 0) {
1166
        average_rbs_per_user[CC_id] = 0;
1167
      } else if (total_ue_count == 1 ) { // increase the available RBs, special case,
1168 1169
        average_rbs_per_user[CC_id] = N_RB_UL-first_rb[CC_id]+1;
      } else if( (total_ue_count <= (N_RB_DL-first_rb[CC_id])) &&
1170
                 (total_ue_count <= max_num_ue_to_be_scheduled)) {
1171
        average_rbs_per_user[CC_id] = (uint16_t) floor((N_RB_UL-first_rb[CC_id])/total_ue_count);
1172
      } else if (max_num_ue_to_be_scheduled > 0 ) {
1173
        average_rbs_per_user[CC_id] = (uint16_t) floor((N_RB_UL-first_rb[CC_id])/max_num_ue_to_be_scheduled);
1174
      } else {
1175 1176 1177
        average_rbs_per_user[CC_id]=1;
        LOG_W(MAC,"[eNB %d] frame %d subframe %d: UE %d CC %d: can't get average rb per user (should not be here)\n",
              module_idP,frameP,subframeP,UE_id,CC_id);
1178 1179 1180
      }
    }
  }
1181 1182 1183
  if (total_ue_count > 0)
    LOG_D(MAC,"[eNB %d] Frame %d subframe %d: total ue to be scheduled %d/%d\n",
	  module_idP, frameP, subframeP,total_ue_count, max_num_ue_to_be_scheduled);
1184

1185
  //LOG_D(MAC,"step3\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
1186

1187 1188 1189 1190
  // step 3: assigne RBS
  for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) {
    rnti = UE_RNTI(module_idP,i);

1191
    if (rnti==NOT_A_RNTI)
1192
      continue;
kaltenbe's avatar
kaltenbe committed
1193 1194
    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
      continue;
1195

1196
    UE_id = i;
1197 1198

    for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
1199 1200
      // This is the actual CC_id in the list
      CC_id = UE_list->ordered_ULCCids[n][UE_id];
1201
      harq_pid = subframe2harqpid(&RC.mac[module_idP]->common_channels[CC_id],frameP,subframeP);
1202

1203

1204
      //      mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL);
1205

1206
      if(UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id]>0) {
1207
        nb_allocated_rbs[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid];
1208
      } else {
1209
        nb_allocated_rbs[CC_id][UE_id] = cmin(UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul, average_rbs_per_user[CC_id]);
1210
      }
1211

1212
      total_allocated_rbs[CC_id]+= nb_allocated_rbs[CC_id][UE_id];
1213
      LOG_D(MAC,"In ulsch_preprocessor: assigning %d RBs for UE %d/%x CCid %d, harq_pid %d\n",nb_allocated_rbs[CC_id][UE_id],UE_id,rnti,CC_id,harq_pid);
1214 1215
    }
  }
1216

1217
  // step 4: assigne the remaining RBs and set the pre_allocated rbs accordingly
1218 1219 1220 1221 1222
  for(r=0; r<2; r++) {

    for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) {
      rnti = UE_RNTI(module_idP,i);

1223
      if (rnti==NOT_A_RNTI)
1224
        continue;
kaltenbe's avatar
kaltenbe committed
1225 1226
      if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
	continue;
1227
      UE_id = i;
1228 1229 1230 1231 1232

      for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
        // This is the actual CC_id in the list
        CC_id = UE_list->ordered_ULCCids[n][UE_id];
        UE_template = &UE_list->UE_template[CC_id][UE_id];
1233
        total_remaining_rbs[CC_id]=N_RB_UL - first_rb[CC_id] - total_allocated_rbs[CC_id];
1234

1235
        if (total_ue_count == 1 ) {
1236
          total_remaining_rbs[CC_id]+=1;
1237
        }
1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251

        if ( r == 0 ) {
          while ( (UE_template->pre_allocated_nb_rb_ul > 0 ) &&
                  (nb_allocated_rbs[CC_id][UE_id] < UE_template->pre_allocated_nb_rb_ul) &&
                  (total_remaining_rbs[CC_id] > 0)) {
            nb_allocated_rbs[CC_id][UE_id] = cmin(nb_allocated_rbs[CC_id][UE_id]+1,UE_template->pre_allocated_nb_rb_ul);
            total_remaining_rbs[CC_id]--;
            total_allocated_rbs[CC_id]++;
          }
        } else {
          UE_template->pre_allocated_nb_rb_ul= nb_allocated_rbs[CC_id][UE_id];
          LOG_D(MAC,"******************UL Scheduling Information for UE%d CC_id %d ************************\n",UE_id, CC_id);
          LOG_D(MAC,"[eNB %d] total RB allocated for UE%d CC_id %d  = %d\n", module_idP, UE_id, CC_id, UE_template->pre_allocated_nb_rb_ul);
        }
1252 1253 1254
      }
    }
  }
1255 1256 1257

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {

1258
    if (total_allocated_rbs[CC_id]>0) {
1259
      LOG_D(MAC,"[eNB %d] total RB allocated for all UEs = %d/%d\n", module_idP, total_allocated_rbs[CC_id], N_RB_UL - first_rb[CC_id]);
1260
    }
1261
  }
1262 1263 1264 1265 1266 1267
}


void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subframeP, uint16_t *first_rb)
{

1268 1269 1270 1271
  int                i;
  uint16_t           n,UE_id;
  uint8_t            CC_id;
  rnti_t             rnti           = -1;
1272
  int                mcs;
Raymond Knopp's avatar
 
Raymond Knopp committed
1273
  int                rb_table_index=0,tbs,tx_power;
1274
  eNB_MAC_INST       *eNB = RC.mac[module_idP];
1275 1276
  UE_list_t          *UE_list = &eNB->UE_list;

1277
  UE_TEMPLATE       *UE_template;
1278 1279
  int Ncp;
  int N_RB_UL;
1280

1281 1282
  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
    if (UE_list->active[i] != TRUE) continue;
1283 1284 1285

    rnti = UE_RNTI(module_idP,i);

1286
    if (rnti==NOT_A_RNTI)
1287
      continue;
kaltenbe's avatar
kaltenbe committed
1288 1289
    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
      continue;
1290

1291 1292 1293 1294
    if (UE_list->UE_sched_ctrl[i].phr_received == 1)
      mcs = 20; // if we've received the power headroom information the UE, we can go to maximum mcs
    else
      mcs = 10; // otherwise, limit to QPSK PUSCH
1295 1296

    UE_id = i;
1297 1298

    for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
1299 1300
      // This is the actual CC_id in the list
      CC_id = UE_list->ordered_ULCCids[n][UE_id];
1301

1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
      if (CC_id >= MAX_NUM_CCs) {
        LOG_E( MAC, "CC_id %u should be < %u, loop n=%u < numactiveULCCs[%u]=%u",
               CC_id,
               MAX_NUM_CCs,
               n,
               UE_id,
               UE_list->numactiveULCCs[UE_id]);
      }

      AssertFatal( CC_id < MAX_NUM_CCs, "CC_id %u should be < %u, loop n=%u < numactiveULCCs[%u]=%u",
                   CC_id,
                   MAX_NUM_CCs,
                   n,
                   UE_id,
                   UE_list->numactiveULCCs[UE_id]);
1317

1318
      UE_template = &UE_list->UE_template[CC_id][UE_id];
1319

1320 1321
      Ncp     = RC.mac[module_idP]->common_channels[CC_id].Ncp;
      N_RB_UL = to_prb(RC.mac[module_idP]->common_channels[CC_id].ul_Bandwidth);
1322
      // if this UE has UL traffic
1323
      if (UE_template->ul_total_buffer > 0 ) {
1324

1325

Raymond Knopp's avatar
Raymond Knopp committed
1326
        tbs = get_TBS_UL(mcs,3)<<3;  // 1 or 2 PRB with cqi enabled does not work well!
Cedric Roux's avatar
Cedric Roux committed
1327
        rb_table_index = 2;
1328

1329
        // fixme: set use_srs flag
1330
        tx_power= estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,Ncp,0);
1331

1332
        while ((((UE_template->phr_info - tx_power) < 0 ) || (tbs > UE_template->ul_total_buffer))&&
1333 1334 1335
               (mcs > 3)) {
          // LOG_I(MAC,"UE_template->phr_info %d tx_power %d mcs %d\n", UE_template->phr_info,tx_power, mcs);
          mcs--;
Raymond Knopp's avatar
Raymond Knopp committed
1336
          tbs = get_TBS_UL(mcs,rb_table[rb_table_index])<<3;
1337
          tx_power = estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,Ncp,0); // fixme: set use_srs
1338 1339 1340
        }

        while ((tbs < UE_template->ul_total_buffer) &&
1341
               (rb_table[rb_table_index]<(N_RB_UL-first_rb[CC_id])) &&
1342 1343
               ((UE_template->phr_info - tx_power) > 0) &&
               (rb_table_index < 32 )) {
1344
   
1345
          rb_table_index++;
Raymond Knopp's avatar
Raymond Knopp committed
1346
          tbs = get_TBS_UL(mcs,rb_table[rb_table_index])<<3;
1347
          tx_power = estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,Ncp,0);
1348 1349
        }

1350
        UE_template->ue_tx_power = tx_power;
1351

1352
        if (rb_table[rb_table_index]>(N_RB_UL-first_rb[CC_id]-1)) {
1353 1354 1355
          rb_table_index--;
        }

Raymond Knopp's avatar
Raymond Knopp committed
1356
        // 1 or 2 PRB with cqi enabled does not work well
1357
	if (rb_table[rb_table_index]<3) {
1358
          rb_table_index=2; //3PRB
1359
        }
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369

        UE_template->pre_assigned_mcs_ul=mcs;
        UE_template->pre_allocated_rb_table_index_ul=rb_table_index;
        UE_template->pre_allocated_nb_rb_ul= rb_table[rb_table_index];
        LOG_D(MAC,"[eNB %d] frame %d subframe %d: for UE %d CC %d: pre-assigned mcs %d, pre-allocated rb_table[%d]=%d RBs (phr %d, tx power %d)\n",
              module_idP, frameP, subframeP, UE_id, CC_id,
              UE_template->pre_assigned_mcs_ul,
              UE_template->pre_allocated_rb_table_index_ul,
              UE_template->pre_allocated_nb_rb_ul,
              UE_template->phr_info,tx_power);
1370
      } else {
Cedric Roux's avatar
Cedric Roux committed
1371 1372 1373 1374 1375 1376 1377 1378 1379
        /* if UE has pending scheduling request then pre-allocate 3 RBs */
        //if (UE_template->ul_active == 1 && UE_template->ul_SR == 1) {
        if (UE_is_to_be_scheduled(module_idP, CC_id, i)) {
          UE_template->pre_allocated_rb_table_index_ul = 2;
          UE_template->pre_allocated_nb_rb_ul          = 3;
        } else {
          UE_template->pre_allocated_rb_table_index_ul=-1;
          UE_template->pre_allocated_nb_rb_ul=0;
        }
1380 1381 1382 1383 1384
      }
    }
  }
}

1385 1386 1387 1388 1389 1390 1391 1392 1393
struct sort_ue_ul_params {
  int module_idP;
  int frameP;
  int subframeP;
};

static int ue_ul_compare(const void *_a, const void *_b, void *_params)
{
  struct sort_ue_ul_params *params = _params;
1394
  UE_list_t *UE_list = &RC.mac[params->module_idP]->UE_list;
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446

  int UE_id1 = *(const int *)_a;
  int UE_id2 = *(const int *)_b;

  int rnti1  = UE_RNTI(params->module_idP, UE_id1);
  int pCCid1 = UE_PCCID(params->module_idP, UE_id1);
  int round1 = maxround(params->module_idP, rnti1, params->frameP, params->subframeP, 1);

  int rnti2  = UE_RNTI(params->module_idP, UE_id2);
  int pCCid2 = UE_PCCID(params->module_idP, UE_id2);
  int round2 = maxround(params->module_idP, rnti2, params->frameP, params->subframeP, 1);

  if (round1 > round2) return -1;
  if (round1 < round2) return 1;

  if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] > UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0])
    return -1;
  if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0])
    return 1;

  if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer > UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer)
    return -1;
  if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer < UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer)
    return 1;

  if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul > UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul)
    return -1;
  if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul < UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul)
    return 1;

  return 0;

#if 0
  /* The above order derives from the following.
   * The last case is not handled: "if (UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer > 0 )"
   * I don't think it makes a big difference.
   */
      if(round2 > round1) {
        swap_UEs(UE_list,UE_id1,UE_id2,1);
      } else if (round2 == round1) {
        if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) {
          swap_UEs(UE_list,UE_id1,UE_id2,1);
        } else if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer <  UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer) {
          swap_UEs(UE_list,UE_id1,UE_id2,1);
        } else if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul <  UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) {
          if (UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer > 0 ) {
            swap_UEs(UE_list,UE_id1,UE_id2,1);
          }
        }
      }
#endif
}
1447

1448 1449
void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP)
{
1450 1451 1452 1453 1454
  int               i;
  int               list[NUMBER_OF_UE_MAX];
  int               list_size = 0;
  int               rnti;
  struct sort_ue_ul_params params = { module_idP, frameP, subframeP };
1455

1456
  UE_list_t *UE_list = &RC.mac[module_idP]->UE_list;
1457 1458 1459 1460 1461 1462 1463

  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
    rnti = UE_RNTI(module_idP, i);
    if (rnti == NOT_A_RNTI)
      continue;
    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
      continue;
1464

1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480
    list[list_size] = i;
    list_size++;
  }

  qsort_r(list, list_size, sizeof(int), ue_ul_compare, &params);

  if (list_size) {
    for (i = 0; i < list_size-1; i++)
      UE_list->next_ul[list[i]] = list[i+1];
    UE_list->next_ul[list[list_size-1]] = -1;
    UE_list->head_ul = list[0];
  } else {
    UE_list->head_ul = -1;
  }

#if 0
1481 1482 1483
  int               UE_id1,UE_id2;
  int               pCCid1,pCCid2;
  int               round1,round2;
1484
  int               i=0,ii=0;
1485 1486
  rnti_t            rnti1,rnti2;

1487
  UE_list_t *UE_list = &RC.mac[module_idP]->UE_list;
1488 1489

  for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1490 1491

    //LOG_I(MAC,"sort ue ul i %d\n",i);
1492
    for (ii=UE_list->next_ul[i]; ii>=0; ii=UE_list->next_ul[ii]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1493
      //LOG_I(MAC,"sort ul ue 2 ii %d\n",ii);
1494 1495 1496 1497 1498
 
      UE_id1  = i;
      rnti1 = UE_RNTI(module_idP,UE_id1);
      
      if(rnti1 == NOT_A_RNTI)
kaltenbe's avatar
kaltenbe committed
1499 1500 1501
	continue;
      if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
	continue;
1502

Raymond Knopp's avatar
 
Raymond Knopp committed
1503

1504 1505 1506 1507 1508 1509
      pCCid1 = UE_PCCID(module_idP,UE_id1);
      round1  = maxround(module_idP,rnti1,frameP,subframeP,1);
      
      UE_id2  = ii;
      rnti2 = UE_RNTI(module_idP,UE_id2);
      
1510
      if(rnti2 == NOT_A_RNTI)
1511
        continue;
kaltenbe's avatar
kaltenbe committed
1512 1513
      if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1)
	continue;
1514

1515
      pCCid2 = UE_PCCID(module_idP,UE_id2);
1516 1517 1518 1519 1520 1521 1522 1523 1524 1525
      round2  = maxround(module_idP,rnti2,frameP,subframeP,1);

      if(round2 > round1) {
        swap_UEs(UE_list,UE_id1,UE_id2,1);
      } else if (round2 == round1) {
        if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) {
          swap_UEs(UE_list,UE_id1,UE_id2,1);
        } else if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer <  UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer) {
          swap_UEs(UE_list,UE_id1,UE_id2,1);
        } else if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul <  UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) {
1526
          if (UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer > 0 ) {
1527
            swap_UEs(UE_list,UE_id1,UE_id2,1);
1528
          }
1529
        }
1530 1531 1532
      }
    }
  }
1533
#endif
1534
}