pre_processor.c 56.1 KB
Newer Older
1 2 3 4 5
/*
 * 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
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * 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 130 131 132 133
      rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,subframeP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0
#ifdef Rel14
                                     ,0, 0
#endif
                                     );
Raymond Knopp's avatar
 
Raymond Knopp committed
134 135 136
      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 ;
137 138
      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
139 140
      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;
141 142
      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];
143

Cedric Roux's avatar
Cedric Roux committed
144
#ifdef DEBUG_eNB_SCHEDULER
145

Raymond Knopp's avatar
 
Raymond Knopp committed
146 147 148 149
      /* 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)
150
        LOG_D(MAC,
151
              "[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 segmented %d \n",
152 153 154 155 156 157 158
              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
159
#endif
160

Raymond Knopp's avatar
 
Raymond Knopp committed
161
    }
162

163
    //#ifdef DEBUG_eNB_SCHEDULER
Raymond Knopp's avatar
 
Raymond Knopp committed
164 165
    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",
166 167 168 169 170 171
            Mod_id, frameP, subframeP, UE_id,
            UE_template->dl_buffer_total,
            UE_template->dl_pdus_total
           );

    //#endif
172 173 174
  }
}

175

176
// This function returns the estimated number of RBs required by each UE for downlink scheduling
Raymond Knopp's avatar
 
Raymond Knopp committed
177
void assign_rbs_required (module_id_t Mod_id,
178 179 180 181 182
                          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])
{
183

Raymond Knopp's avatar
 
Raymond Knopp committed
184
  uint16_t         TBS = 0;
185

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

191
  // clear rb allocations across all CC_id
192 193 194
  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
195
    pCCid = UE_PCCID(Mod_id,UE_id);
196

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

Raymond Knopp's avatar
 
Raymond Knopp committed
200
      CC_id = UE_list->ordered_CCids[n][UE_id];
201
      eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
202

Cedric Roux's avatar
Cedric Roux committed
203
      eNB_UE_stats->dlsch_mcs1=cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]];
204

Raymond Knopp's avatar
 
Raymond Knopp committed
205
    }
206

Raymond Knopp's avatar
 
Raymond Knopp committed
207
    // provide the list of CCs sorted according to MCS
208
    for (i=0; i<UE_list->numactiveCCs[UE_id]; i++) {
209
      eNB_UE_stats_i = &UE_list->eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]][UE_id];
210
      for (j=i+1; j<UE_list->numactiveCCs[UE_id]; j++) {
211
        DevAssert( j < MAX_NUM_CCs );
212 213 214
	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) {
215 216 217 218
          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;
        }
219
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
220
    }
221 222

    if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total> 0) {
David Price's avatar
David Price committed
223
      //LOG_D(MAC,"[preprocessor] assign RB for UE %d\n",UE_id);
224 225 226

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

229
        if (eNB_UE_stats->dlsch_mcs1==0) {
230 231 232 233
          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];
        }
234

235
        TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]);
236

David Price's avatar
David Price committed
237
        if(0)LOG_D(MAC,"[preprocessor] start RB assignment for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n",
238
              UE_id, CC_id, UE_list->UE_template[pCCid][UE_id].dl_buffer_total,
239
              nb_rbs_required[CC_id][UE_id],eNB_UE_stats->dlsch_mcs1,TBS);
240

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

243 244 245 246
        /* 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];

247
          if (nb_rbs_required[CC_id][UE_id] > N_RB_DL) {
248
            TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,N_RB_DL);
249
            nb_rbs_required[CC_id][UE_id] = N_RB_DL;
250 251 252
            break;
          }

253
          TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]);
254 255 256
        } // 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",
257
              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
258 259 260 261
      }
    }
  }
}
262 263


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

266 267
int maxround(module_id_t Mod_id,uint16_t rnti,int frame,sub_frame_t subframe,uint8_t ul_flag )
{
268

269
  uint8_t round,round_max=0,UE_id;
270
  int CC_id,harq_pid;
271
  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
272
  COMMON_channels_t *cc;
273

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

276 277
    cc = &RC.mac[Mod_id]->common_channels[CC_id];

278
    UE_id = find_UE_id(Mod_id,rnti);
279 280 281 282
    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];
283
    if (round > round_max) {
Raymond Knopp's avatar
 
Raymond Knopp committed
284
      round_max = round;
285
    }
286 287
  }

288
  return round_max;
Raymond Knopp's avatar
 
Raymond Knopp committed
289
}
290

Raymond Knopp's avatar
 
Raymond Knopp committed
291
// This function scans all CC_ids for a particular UE to find the maximum DL CQI
292
// it returns -1 if the UE is not found in PHY layer (get_eNB_UE_stats gives NULL)
293 294
int maxcqi(module_id_t Mod_id,int32_t UE_id)
{
295
  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
296
  int CC_id,n;
Raymond Knopp's avatar
 
Raymond Knopp committed
297
  int CQI = 0;
298

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

Cedric Roux's avatar
Cedric Roux committed
302 303
    if (UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id] > CQI) {
      CQI = UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id];
304
    }
305
  }
306

Cedric Roux's avatar
Cedric Roux committed
307
  return CQI;
Raymond Knopp's avatar
 
Raymond Knopp committed
308
}
309

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

316 317 318
static int ue_dl_compare(const void *_a, const void *_b, void *_params)
{
  struct sort_ue_dl_params *params = _params;
319
  UE_list_t *UE_list = &RC.mac[params->Mod_idP]->UE_list;
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 373

  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
374

375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
        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
}
390

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

402
  UE_list_t *UE_list = &RC.mac[Mod_idP]->UE_list;
403 404

  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
405 406 407 408 409

    if (UE_list->active[i]==FALSE) continue;
    if ((rnti = UE_RNTI(Mod_idP, i)) == NOT_A_RNTI) continue;
    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) continue;

410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
    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
426 427


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

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

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

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

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

450 451
      UE_id2 = ii;
      rnti2 = UE_RNTI(Mod_idP,UE_id2);
452 453
      if(rnti2 == NOT_A_RNTI)
        continue;
kaltenbe's avatar
kaltenbe committed
454 455
      if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1)
	continue;
456
      cqi2    = maxcqi(Mod_idP,UE_id2);
457
      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
458
      pCC_id2 = UE_PCCID(Mod_idP,UE_id2);
459

460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
      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
482 483
      }
    }
484
  }
485
#endif
486 487
}

488

Raymond Knopp's avatar
 
Raymond Knopp committed
489 490


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

499
  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
500
  unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX];
501
  int                     UE_id, i; 
502
  uint16_t                ii,j;
Raymond Knopp's avatar
 
Raymond Knopp committed
503 504 505
  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];
506
  uint16_t                average_rbs_per_user[MAX_NUM_CCs] = {0};
507
  rnti_t             rnti;
Raymond Knopp's avatar
 
Raymond Knopp committed
508
  int                min_rb_unit[MAX_NUM_CCs];
509
  uint16_t r1=0;
510
  uint8_t CC_id;
511
  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
512

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

#ifdef TM5
520
  int harq_pid1=0;
521 522 523 524 525 526 527 528
  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
529 530

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

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


Raymond Knopp's avatar
 
Raymond Knopp committed
536

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

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

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

546

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

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


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

Raymond Knopp's avatar
 
Raymond Knopp committed
565 566


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

Raymond Knopp's avatar
 
Raymond Knopp committed
570 571


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


Raymond Knopp's avatar
 
Raymond Knopp committed
576

577
  total_ue_count =0;
578

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

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

589
    for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
590
      CC_id = UE_list->ordered_CCids[ii][UE_id];
591
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
592 593 594 595
      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];
596

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

599

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

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


610
      // hypothetical assignment
611 612 613
      /*
       * 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
614
       * priority. Concerning the hypothetical assignment, we should assign more
615 616 617 618 619
       * 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.
       */

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

622
      if (total_ue_count == 0) {
623
        average_rbs_per_user[CC_id] = 0;
624 625
      } 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);
626
      } else {
627
        average_rbs_per_user[CC_id] = min_rb_unit[CC_id]; // consider the total number of use that can be scheduled UE
628
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
629 630
    }
  }
631

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

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

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

Cedric Roux's avatar
Cedric Roux committed
647 648 649
      // 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) {
650
        nb_rbs_required_remaining_1[CC_id][i] = nb_rbs_required[CC_id][i];
651
      } else {
652 653
        nb_rbs_required_remaining_1[CC_id][i] = cmin(average_rbs_per_user[CC_id],nb_rbs_required[CC_id][i]);

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

658
  //Allocation to UEs is done in 2 rounds,
659 660
  // 1st stage: average number of RBs allocated to each UE
  // 2nd stage: remaining RBs are allocated to high priority UEs
661 662 663 664 665 666
  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];

667
        if(r1 == 0) {
668
          nb_rbs_required_remaining[CC_id][i] = nb_rbs_required_remaining_1[CC_id][i];
669
        } else { // rb required based only on the buffer - rb allloctaed in the 1st round + extra reaming rb form the 1st round
670
          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
671
if (nb_rbs_required_remaining[CC_id][i]<0) abort();
672
        }
673 674

        if (nb_rbs_required[CC_id][i]> 0 )
675
          if (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",
676 677 678 679
                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],
680
                UE_list->UE_sched_ctrl[i].pre_nb_available_rbs[CC_id],
681 682 683
                N_RBG[CC_id],
                min_rb_unit[CC_id]);

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

687
    if (total_ue_count > 0 ) {
688 689 690 691 692
      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];
693
	  ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
694
	  round    = ue_sched_ctl->round[CC_id][harq_pid];
695 696 697 698

          rnti = UE_RNTI(Mod_id,UE_id);

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

704
          transmission_mode = get_tmode(Mod_id,CC_id,UE_id);
705 706
	  //          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);
707 708 709 710 711 712 713 714 715 716 717 718
          /* 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],
719
                                                  to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth),
720 721 722 723 724
                                                  nb_rbs_required,
                                                  nb_rbs_required_remaining,
                                                  rballoc_sub,
                                                  MIMO_mode_indicator);

725
#ifdef TM5
726 727 728 729

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

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

734 735
              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)) ) &&
736 737 738 739 740 741
                  (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);
742 743
		  ue_sched_ctl2 = &UE_list->UE_sched_ctrl[UE_id2];
		  round2    = ue_sched_ctl2->round[CC_id];
744
                  if(rnti2 == NOT_A_RNTI)
745
                    continue;
kaltenbe's avatar
kaltenbe committed
746 747
		  if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1)
		    continue;
748

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

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

757 758
                    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))  ) &&
759 760 761 762 763
                        (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;
764 765
                        ue_sched_ctl->rballoc_sub_UE[CC_id][j] = 1;
                        ue_sched_ctl2->rballoc_sub_UE[CC_id][j] = 1;
766 767 768 769
                        MIMO_mode_indicator[CC_id][j] = 0;

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

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


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

                        break;
                      }
                    }
                  }
                }
              }
            }
          }

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

#ifdef TM5

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

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

828
    if((i1 < N_RBG[CC_id]) && (i2>0) && (i3==0)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
829
      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;
830
    }
831

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

836
    if((i1 < N_RBG[CC_id]) && (i3 > 0)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
837
      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;
838
    }
839

Raymond Knopp's avatar
 
Raymond Knopp committed
840
    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;
841

842 843
  }

844 845 846
#endif

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

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

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

        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];
861
          //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]);
862 863 864
        }

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

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

873
void dlsch_scheduler_pre_processor_reset (int module_idP,
874 875 876 877 878 879 880 881 882 883
					  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])
  
884
{
885
  int i,j;
886
  UE_list_t *UE_list=&RC.mac[module_idP]->UE_list;
887
  UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[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
  //rnti_t rnti = UE_RNTI(module_idP,UE_id);
898
  //LOG_D(MAC,"Running preprocessor for UE %d (%x)\n",UE_id,rnti);
899
  // initialize harq_pid and round
900

Cedric Roux's avatar
Cedric Roux committed
901 902
  if (ue_sched_ctl->ta_timer) ue_sched_ctl->ta_timer--;

903 904 905
  /*
  eNB_UE_stats *eNB_UE_stats;

906 907 908
  if (eNB_UE_stats == NULL)
    return;

909
  
910 911 912 913
  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],
914
				    openair_harq_DL);
915 916
  

917
  if (ue_sched_ctl->ta_timer == 0) {
918

919 920 921
    // 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
922
    switch (N_RB_DL) {
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943
    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:
944
	ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/16;
945 946 947 948 949 950 951 952 953
      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
  }
954 955
  

956 957 958
  if (UE_id==0) {
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_TIMING_ADVANCE,ue_sched_ctl->ta_update);
  }
959 960
  */

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

1005
    ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0;
1006
    rballoc_sub[CC_id][i] = 0;
Cedric Roux's avatar
Cedric Roux committed
1007 1008 1009 1010 1011 1012 1013 1014
#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)
1015 1016 1017
      rballoc_sub[CC_id][i]=1;
#endif
    // for SI-RNTI,RA-RNTI and P-RNTI allocations
Cedric Roux's avatar
Cedric Roux committed
1018 1019
    for (j = 0; j < rb_size; j++) {
      if (vrb_map[j+(i*RBGsize)] != 0)  {
1020
	rballoc_sub[CC_id][i] = 1;
1021
	//LOG_D(MAC,"Frame %d, subframe %d : vrb %d allocated\n",frameP,subframeP,j+(i*RBGsize));
1022 1023 1024
	break;
      }
    }
1025
    //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]);
1026
    MIMO_mode_indicator[CC_id][i] = 2;
1027 1028 1029 1030 1031
  }
}


void dlsch_scheduler_pre_processor_allocate (module_id_t   Mod_id,
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
    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])
{

1044
  int i;
1045
  UE_list_t *UE_list=&RC.mac[Mod_id]->UE_list;
1046
  UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
1047 1048 1049 1050

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

    if((rballoc_sub[CC_id][i] == 0)           &&
1051
        (ue_sched_ctl->rballoc_sub_UE[CC_id][i] == 0) &&
1052
        (nb_rbs_required_remaining[CC_id][UE_id]>0)   &&
1053
        (ue_sched_ctl->pre_nb_available_rbs[CC_id] < nb_rbs_required[CC_id][UE_id])) {
1054

1055
      // if this UE is not scheduled for TM5
1056
      if (ue_sched_ctl->dl_pow_off[CC_id] != 0 )  {
1057

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


1087
/// ULSCH PRE_PROCESSOR
1088

1089

1090
void ulsch_scheduler_pre_processor(module_id_t module_idP,
1091 1092
                                   int frameP,
                                   sub_frame_t subframeP,
1093
                                   uint16_t *first_rb)
1094
{
1095 1096 1097

  int16_t            i;
  uint16_t           UE_id,n,r;
1098
  uint8_t            CC_id, harq_pid;
1099 1100
  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];
1101 1102 1103 1104 1105
  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;
1106 1107
  int                N_RB_DL;
  int                N_RB_UL;
1108
  //LOG_D(MAC,"In ulsch_preprocessor: assign max mcs min rb\n");
1109 1110
  // 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);
1111

1112
  //LOG_D(MAC,"In ulsch_preprocessor: sort ue \n");
1113
  // sort ues
1114 1115
  sort_ue_ul (module_idP,frameP, subframeP);

1116

1117 1118
  // we need to distribute RBs among UEs
  // step1:  reset the vars
1119
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1120 1121 1122 1123 1124
    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;
1125 1126

    for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) {
1127 1128 1129 1130
      nb_allocated_rbs[CC_id][i]=0;
    }
  }

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

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

    rnti = UE_RNTI(module_idP,i);

1140
    if (rnti==NOT_A_RNTI)
1141 1142
      continue;

kaltenbe's avatar
kaltenbe committed
1143 1144 1145
    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
      continue;

1146

1147
    UE_id = i;
1148

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

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

      max_num_ue_to_be_scheduled+=1;
1167

1168
      if (total_ue_count == 0) {
1169
        average_rbs_per_user[CC_id] = 0;
1170
      } else if (total_ue_count == 1 ) { // increase the available RBs, special case,
1171 1172
        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])) &&
1173
                 (total_ue_count <= max_num_ue_to_be_scheduled)) {
1174
        average_rbs_per_user[CC_id] = (uint16_t) floor((N_RB_UL-first_rb[CC_id])/total_ue_count);
1175
      } else if (max_num_ue_to_be_scheduled > 0 ) {
1176
        average_rbs_per_user[CC_id] = (uint16_t) floor((N_RB_UL-first_rb[CC_id])/max_num_ue_to_be_scheduled);
1177
      } else {
1178 1179 1180
        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);
1181 1182 1183
      }
    }
  }
1184
  //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);
1185

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

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

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

1197
    UE_id = i;
1198 1199

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

1204

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

1207
      if(UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id]>0) {
1208
        nb_allocated_rbs[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid];
1209
      } else {
1210
        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]);
1211
      }
1212

1213
      total_allocated_rbs[CC_id]+= nb_allocated_rbs[CC_id][UE_id];
1214
      //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);
1215 1216
    }
  }
1217

1218
  // step 4: assigne the remaining RBs and set the pre_allocated rbs accordingly
1219 1220 1221 1222 1223
  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);

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

      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];
1234
        total_remaining_rbs[CC_id]=N_RB_UL - first_rb[CC_id] - total_allocated_rbs[CC_id];
1235

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

        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];
1250 1251
          //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 1258

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

1259
    if (total_allocated_rbs[CC_id]>0) {
1260
      //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]);
1261
    }
1262
  }
1263 1264 1265 1266 1267 1268
}


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

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

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

1282
  //LOG_D(MAC, "%s() Enter\n", __FUNCTION__);
1283

1284 1285
  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
    if (UE_list->active[i] != TRUE) continue;
1286 1287 1288

    rnti = UE_RNTI(module_idP,i);

1289
    //LOG_D(MAC, "%s() UE active rnti:%04x UE_list->UE_sched_ctrl[i].ul_out_of_sync:%d UE_list->UE_sched_ctrl[i].phr_received:%d numactiveULCCs[UE_id]:%d UE_list->UE_template[CC_id][UE_id].ul_total_buffer:%d\n", __FUNCTION__, rnti, UE_list->UE_sched_ctrl[i].ul_out_of_sync, UE_list->UE_sched_ctrl[i].phr_received, UE_list->numactiveULCCs[i], UE_list->UE_template[CC_id][i].ul_total_buffer);
1290

1291
    if (rnti==NOT_A_RNTI)
1292
      continue;
kaltenbe's avatar
kaltenbe committed
1293 1294
    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
      continue;
1295

1296 1297 1298 1299
    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
1300 1301

    UE_id = i;
1302 1303

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

1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321
      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]);
1322

1323
      UE_template = &UE_list->UE_template[CC_id][UE_id];
1324

1325 1326
      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);
1327
      // if this UE has UL traffic
1328
      if (UE_template->ul_total_buffer > 0 ) {
1329

1330

Raymond Knopp's avatar
Raymond Knopp committed
1331
        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
1332
        rb_table_index = 2;
1333

1334
        // fixme: set use_srs flag
1335
        tx_power= estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,Ncp,0);
1336

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

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

1355
        UE_template->ue_tx_power = tx_power;
1356

1357
        if (rb_table[rb_table_index]>(N_RB_UL-first_rb[CC_id]-1)) {
1358 1359 1360
          rb_table_index--;
        }

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

        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);
1375
      } else {
1376
        //LOG_E(MAC,"no ul buffer");
1377

Cedric Roux's avatar
Cedric Roux committed
1378 1379 1380
        /* 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)) {
1381
          /* use QPSK mcs */
1382
          UE_template->pre_assigned_mcs_ul             = 10;
Cedric Roux's avatar
Cedric Roux committed
1383 1384 1385
          UE_template->pre_allocated_rb_table_index_ul = 2;
          UE_template->pre_allocated_nb_rb_ul          = 3;
        } else {
1386
          UE_template->pre_assigned_mcs_ul             = 0;
1387 1388
          UE_template->pre_allocated_rb_table_index_ul = -1;
          UE_template->pre_allocated_nb_rb_ul          = 0;
Cedric Roux's avatar
Cedric Roux committed
1389
        }
1390 1391 1392 1393 1394
      }
    }
  }
}

1395 1396 1397 1398 1399 1400 1401 1402 1403
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;
1404
  UE_list_t *UE_list = &RC.mac[params->module_idP]->UE_list;
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 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456

  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
}
1457

1458 1459
void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP)
{
1460 1461 1462 1463 1464
  int               i;
  int               list[NUMBER_OF_UE_MAX];
  int               list_size = 0;
  int               rnti;
  struct sort_ue_ul_params params = { module_idP, frameP, subframeP };
1465

1466
  UE_list_t *UE_list = &RC.mac[module_idP]->UE_list;
1467 1468

  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
1469 1470 1471
    if (UE_list->active[i] == FALSE) continue;
    if ((rnti = UE_RNTI(module_idP, i)) == NOT_A_RNTI) continue;
    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) continue;
1472

1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
    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
1489 1490 1491
  int               UE_id1,UE_id2;
  int               pCCid1,pCCid2;
  int               round1,round2;
1492
  int               i=0,ii=0;
1493 1494
  rnti_t            rnti1,rnti2;

1495
  UE_list_t *UE_list = &RC.mac[module_idP]->UE_list;
1496 1497

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

    //LOG_I(MAC,"sort ue ul i %d\n",i);
1500
    for (ii=UE_list->next_ul[i]; ii>=0; ii=UE_list->next_ul[ii]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1501
      //LOG_I(MAC,"sort ul ue 2 ii %d\n",ii);
1502 1503 1504 1505 1506
 
      UE_id1  = i;
      rnti1 = UE_RNTI(module_idP,UE_id1);
      
      if(rnti1 == NOT_A_RNTI)
kaltenbe's avatar
kaltenbe committed
1507 1508 1509
	continue;
      if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
	continue;
1510

Raymond Knopp's avatar
 
Raymond Knopp committed
1511

1512 1513 1514 1515 1516 1517
      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);
      
1518
      if(rnti2 == NOT_A_RNTI)
1519
        continue;
kaltenbe's avatar
kaltenbe committed
1520 1521
      if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1)
	continue;
1522

1523
      pCCid2 = UE_PCCID(module_idP,UE_id2);
1524 1525 1526 1527 1528 1529 1530 1531 1532 1533
      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) {
1534
          if (UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer > 0 ) {
1535
            swap_UEs(UE_list,UE_id1,UE_id2,1);
1536
          }
1537
        }
1538 1539 1540
      }
    }
  }
1541
#endif
1542
}