dlsch_decoding.c 30.9 KB
Newer Older
1
/*******************************************************************************
2
    OpenAirInterface
ghaddab's avatar
ghaddab committed
3
    Copyright(c) 1999 - 2014 Eurecom
4

ghaddab's avatar
ghaddab committed
5 6 7 8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9 10


ghaddab's avatar
ghaddab committed
11 12 13 14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

ghaddab's avatar
ghaddab committed
16
    You should have received a copy of the GNU General Public License
17 18
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
ghaddab's avatar
ghaddab committed
19
   see <http://www.gnu.org/licenses/>.
20 21

  Contact Information
ghaddab's avatar
ghaddab committed
22 23
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

ghaddab's avatar
ghaddab committed
28
 *******************************************************************************/
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

/*! \file PHY/LTE_TRANSPORT/dlsch_decoding.c
* \brief Top-level routines for decoding  Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/

//#include "defs.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "PHY/CODING/extern.h"
#include "SCHED/extern.h"
#include "SIMULATION/TOOLS/defs.h"
Raymond Knopp's avatar
 
Raymond Knopp committed
47
//#define DEBUG_DLSCH_DECODING
48
 
49

50 51
void free_ue_dlsch(LTE_UE_DLSCH_t *dlsch)
{
52 53 54 55

  int i,r;

  if (dlsch) {
56
    for (i=0; i<dlsch->Mdlharq; i++) {
57
      if (dlsch->harq_processes[i]) {
58 59 60 61 62 63
        if (dlsch->harq_processes[i]->b) {
          free16(dlsch->harq_processes[i]->b,MAX_DLSCH_PAYLOAD_BYTES);
          dlsch->harq_processes[i]->b = NULL;
        }

        for (r=0; r<MAX_NUM_DLSCH_SEGMENTS; r++) {
64 65 66
          free16(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768);
          dlsch->harq_processes[i]->c[r] = NULL;
        }
67 68 69 70 71 72 73 74 75

        for (r=0; r<MAX_NUM_DLSCH_SEGMENTS; r++)
          if (dlsch->harq_processes[i]->d[r]) {
            free16(dlsch->harq_processes[i]->d[r],((3*8*6144)+12+96)*sizeof(short));
            dlsch->harq_processes[i]->d[r] = NULL;
          }

        free16(dlsch->harq_processes[i],sizeof(LTE_DL_UE_HARQ_t));
        dlsch->harq_processes[i] = NULL;
76 77
      }
    }
78 79 80

    free16(dlsch,sizeof(LTE_UE_DLSCH_t));
    dlsch = NULL;
81 82 83
  }
}

84
LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag)
85
{
86 87 88

  LTE_UE_DLSCH_t *dlsch;
  uint8_t exit_flag = 0,i,r;
89

90
  unsigned char bw_scaling =1;
91 92 93

  switch (N_RB_DL) {
  case 6:
94 95
    bw_scaling =16;
    break;
96

97 98 99
  case 25:
    bw_scaling =4;
    break;
100 101

  case 50:
102 103
    bw_scaling =2;
    break;
104

105 106 107 108
  default:
    bw_scaling =1;
    break;
  }
109

110
  dlsch = (LTE_UE_DLSCH_t *)malloc16(sizeof(LTE_UE_DLSCH_t));
111

112
  if (dlsch) {
113
    memset(dlsch,0,sizeof(LTE_UE_DLSCH_t));
114 115
    dlsch->Kmimo = Kmimo;
    dlsch->Mdlharq = Mdlharq;
116
    dlsch->Nsoft = Nsoft;
117 118
    dlsch->max_turbo_iterations = max_turbo_iterations;

119
    for (i=0; i<Mdlharq; i++) {
120
      //      printf("new_ue_dlsch: Harq process %d\n",i);
121
      dlsch->harq_processes[i] = (LTE_DL_UE_HARQ_t *)malloc16(sizeof(LTE_DL_UE_HARQ_t));
122

123
      if (dlsch->harq_processes[i]) {
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
        memset(dlsch->harq_processes[i],0,sizeof(LTE_DL_UE_HARQ_t));
        dlsch->harq_processes[i]->first_tx=1;
        dlsch->harq_processes[i]->b = (uint8_t*)malloc16(MAX_DLSCH_PAYLOAD_BYTES/bw_scaling);

        if (dlsch->harq_processes[i]->b)
          memset(dlsch->harq_processes[i]->b,0,MAX_DLSCH_PAYLOAD_BYTES/bw_scaling);
        else
          exit_flag=3;

        if (abstraction_flag == 0) {
          for (r=0; r<MAX_NUM_DLSCH_SEGMENTS/bw_scaling; r++) {
            dlsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(((r==0)?8:0) + 3+ 768);

            if (dlsch->harq_processes[i]->c[r])
              memset(dlsch->harq_processes[i]->c[r],0,((r==0)?8:0) + 3+ 768);
            else
              exit_flag=2;

            dlsch->harq_processes[i]->d[r] = (short*)malloc16(((3*8*6144)+12+96)*sizeof(short));

            if (dlsch->harq_processes[i]->d[r])
              memset(dlsch->harq_processes[i]->d[r],0,((3*8*6144)+12+96)*sizeof(short));
            else
              exit_flag=2;
          }
        }
      } else {
        exit_flag=1;
152 153 154 155 156 157
      }
    }

    if (exit_flag==0)
      return(dlsch);
  }
158

159
  printf("new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(LTE_DL_UE_HARQ_t), exit_flag);
160 161 162 163 164 165 166 167 168 169 170 171 172
  free_ue_dlsch(dlsch);

  return(NULL);
}

uint32_t  dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
                         short *dlsch_llr,
                         LTE_DL_FRAME_PARMS *frame_parms,
                         LTE_UE_DLSCH_t *dlsch,
                         LTE_DL_UE_HARQ_t *harq_process,
                         uint8_t subframe,
                         uint8_t harq_pid,
                         uint8_t is_crnti,
173 174 175 176
                         uint8_t llr8_flag)
{


177 178 179 180 181 182
  time_stats_t *dlsch_rate_unmatching_stats=&phy_vars_ue->dlsch_rate_unmatching_stats;
  time_stats_t *dlsch_turbo_decoding_stats=&phy_vars_ue->dlsch_turbo_decoding_stats;
  time_stats_t *dlsch_deinterleaving_stats=&phy_vars_ue->dlsch_deinterleaving_stats;
  uint32_t A,E;
  uint32_t G;
  uint32_t ret,offset;
183
  uint16_t iind;
184 185 186 187 188
  //  uint8_t dummy_channel_output[(3*8*block_length)+12];
  short dummy_w[MAX_NUM_DLSCH_SEGMENTS][3*(6144+64)];
  uint32_t r,r_offset=0,Kr,Kr_bytes,err_flag=0;
  uint8_t crc_type;
#ifdef DEBUG_DLSCH_DECODING
189
  uint16_t i;
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
#endif
#ifdef __AVX2__
  int Kr_last,skipped_last=0;
  uint8_t (*tc_2cw)(int16_t *y,
		    int16_t *y2,
		    uint8_t *,
		    uint8_t *,
		    uint16_t,
		    uint16_t,
		    uint16_t,
		    uint8_t,
		    uint8_t,
		    uint8_t,
		    time_stats_t *,
		    time_stats_t *,
		    time_stats_t *,
		    time_stats_t *,
		    time_stats_t *,
		    time_stats_t *,
		    time_stats_t *);

211 212
#endif
  uint8_t (*tc)(int16_t *y,
213 214 215 216 217 218 219 220 221 222 223 224 225 226
                uint8_t *,
                uint16_t,
                uint16_t,
                uint16_t,
                uint8_t,
                uint8_t,
                uint8_t,
                time_stats_t *,
                time_stats_t *,
                time_stats_t *,
                time_stats_t *,
                time_stats_t *,
                time_stats_t *,
                time_stats_t *);
227

228 229 230



231
  if (!dlsch_llr) {
232
    printf("dlsch_decoding.c: NULL dlsch_llr pointer\n");
233 234 235 236
    return(dlsch->max_turbo_iterations);
  }

  if (!harq_process) {
237
    printf("dlsch_decoding.c: NULL harq_process pointer\n");
238
    return(dlsch->max_turbo_iterations);
239 240 241
  }

  if (!frame_parms) {
242
    printf("dlsch_decoding.c: NULL frame_parms pointer\n");
243
    return(dlsch->max_turbo_iterations);
244
  }
245

246
  if (subframe>9) {
247
    printf("dlsch_decoding.c: Illegal subframe index %d\n",subframe);
248
    return(dlsch->max_turbo_iterations);
249 250
  }

251 252 253 254
  if (llr8_flag == 0) {
#ifdef __AVX2__
    tc_2cw = phy_threegpplte_turbo_decoder16avx2;
#endif
255
    tc = phy_threegpplte_turbo_decoder16;
256
  }
257 258
  else
    tc = phy_threegpplte_turbo_decoder8;
259

260 261 262 263
  //  nb_rb = dlsch->nb_rb;

  /*
  if (nb_rb > frame_parms->N_RB_DL) {
264
    printf("dlsch_decoding.c: Illegal nb_rb %d\n",nb_rb);
265 266 267 268 269
    return(max_turbo_iterations);
    }*/

  /*harq_pid = dlsch->current_harq_pid;
  if (harq_pid >= 8) {
270
    printf("dlsch_decoding.c: Illegal harq_pid %d\n",harq_pid);
271 272 273
    return(max_turbo_iterations);
  }
  */
274 275 276

  harq_process->trials[harq_process->round]++;

277 278 279 280 281 282 283 284
  A = harq_process->TBS; //2072 for QPSK 1/3

  ret = dlsch->max_turbo_iterations;


  G = harq_process->G;
  //get_G(frame_parms,nb_rb,dlsch->rb_alloc,mod_order,num_pdcch_symbols,phy_vars_ue->frame,subframe);

285
  //  printf("DLSCH Decoding, harq_pid %d Ndi %d\n",harq_pid,harq_process->Ndi);
286

287
  if (harq_process->round == 0) {
288 289 290
    // This is a new packet, so compute quantities regarding segmentation
    harq_process->B = A+24;
    lte_segmentation(NULL,
291 292 293 294 295 296 297 298
                     NULL,
                     harq_process->B,
                     &harq_process->C,
                     &harq_process->Cplus,
                     &harq_process->Cminus,
                     &harq_process->Kplus,
                     &harq_process->Kminus,
                     &harq_process->F);
299 300
    //  CLEAR LLR's HERE for first packet in process
  }
301

302 303
  /*
  else {
304
    printf("dlsch_decoding.c: Ndi>0 not checked yet!!\n");
305 306 307 308 309
    return(max_turbo_iterations);
  }
  */
  err_flag = 0;
  r_offset = 0;
310

311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
  unsigned char bw_scaling =1;

  switch (frame_parms->N_RB_DL) {
  case 6:
    bw_scaling =16;
    break;

  case 25:
    bw_scaling =4;
    break;

  case 50:
    bw_scaling =2;
    break;

  default:
    bw_scaling =1;
    break;
  }

331
  if (harq_process->C > MAX_NUM_DLSCH_SEGMENTS/bw_scaling) {
332 333 334
    LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,MAX_NUM_DLSCH_SEGMENTS/bw_scaling);
    return((1+dlsch->max_turbo_iterations));
  }
335 336 337 338
#ifdef DEBUG_DLSCH_DECODING
  printf("Segmentation: C %d, Cminus %d, Kminus %d, Kplus %d\n",harq_process->C,harq_process->Cminus,harq_process->Kminus,harq_process->Kplus);
#endif

339
  for (r=0; r<harq_process->C; r++) {
340

341
    
342 343 344 345 346
    // Get Turbo interleaver parameters
    if (r<harq_process->Cminus)
      Kr = harq_process->Kminus;
    else
      Kr = harq_process->Kplus;
347

348
    Kr_bytes = Kr>>3;
349

350 351 352 353 354 355 356 357 358
    if (Kr_bytes<=64)
      iind = (Kr_bytes-5);
    else if (Kr_bytes <=128)
      iind = 59 + ((Kr_bytes-64)>>1);
    else if (Kr_bytes <= 256)
      iind = 91 + ((Kr_bytes-128)>>2);
    else if (Kr_bytes <= 768)
      iind = 123 + ((Kr_bytes-256)>>3);
    else {
359
      printf("dlsch_decoding: Illegal codeword size %d!!!\n",Kr_bytes);
360
      return(dlsch->max_turbo_iterations);
361
    }
362 363

#ifdef DEBUG_DLSCH_DECODING
364
    printf("f1 %d, f2 %d, F %d\n",f1f2mat_old[2*iind],f1f2mat_old[1+(2*iind)],(r==0) ? harq_process->F : 0);
365 366 367 368
#endif

    start_meas(dlsch_rate_unmatching_stats);
    memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short));
369 370 371
    harq_process->RTC[r] = generate_dummy_w(4+(Kr_bytes*8),
                                            (uint8_t*) &dummy_w[r][0],
                                            (r==0) ? harq_process->F : 0);
372

373
#ifdef DEBUG_DLSCH_DECODING
Raymond Knopp's avatar
 
Raymond Knopp committed
374
    LOG_I(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n",
375 376 377
          harq_pid,r, G,
          Kr*3,
          harq_process->TBS,
378
          harq_process->Qm,
379 380 381 382 383
          harq_process->nb_rb,
          harq_process->Nl,
          harq_process->rvidx,
          harq_process->round);
#endif
384 385 386


    if (lte_rate_matching_turbo_rx(harq_process->RTC[r],
387 388 389 390 391
                                   G,
                                   harq_process->w[r],
                                   (uint8_t*)&dummy_w[r][0],
                                   dlsch_llr+r_offset,
                                   harq_process->C,
392
                                   dlsch->Nsoft,
393 394 395 396
                                   dlsch->Mdlharq,
                                   dlsch->Kmimo,
                                   harq_process->rvidx,
                                   (harq_process->round==0)?1:0,
397
                                   harq_process->Qm,
398 399 400
                                   harq_process->Nl,
                                   r,
                                   &E)==-1) {
401
      stop_meas(dlsch_rate_unmatching_stats);
402
      LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n");
403
      return(dlsch->max_turbo_iterations);
404
    } else
405
      stop_meas(dlsch_rate_unmatching_stats);
406

407 408 409
    r_offset += E;

    /*
410
    printf("Subblock deinterleaving, d %p w %p\n",
411 412
     harq_process->d[r],
     harq_process->w);
413 414
    */
    start_meas(dlsch_deinterleaving_stats);
415 416
    sub_block_deinterleaving_turbo(4+Kr,
                                   &harq_process->d[r][96],
417

418
                                   harq_process->w[r]);
419
    stop_meas(dlsch_deinterleaving_stats);
420 421

#ifdef DEBUG_DLSCH_DECODING
422 423 424 425 426
    /*
    if (r==0) {
              write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0);
              write_output("decoder_in.m","dec",&harq_process->d[0][96],(3*8*Kr_bytes)+12,1,0);
    }
427

428
    printf("decoder input(segment %d) :",r);
429
    int i; for (i=0;i<(3*8*Kr_bytes)+12;i++)
430 431
      printf("%d : %d\n",i,harq_process->d[r][96+i]);
      printf("\n");*/
432
#endif
433

434

435
    //    printf("Clearing c, %p\n",harq_process->c[r]);
436
    memset(harq_process->c[r],0,Kr_bytes);
437

438
    //    printf("done\n");
439
    if (harq_process->C == 1)
440
      crc_type = CRC24_A;
441
    else
442 443
      crc_type = CRC24_B;

444
    /*
445
    printf("decoder input(segment %d)\n",r);
446
    for (i=0;i<(3*8*Kr_bytes)+12;i++)
447 448
      if ((harq_process->d[r][96+i]>7) ||
    (harq_process->d[r][96+i] < -8))
449 450
    printf("%d : %d\n",i,harq_process->d[r][96+i]);
    printf("\n");
451 452
    */

453 454
    //#ifndef __AVX2__
#if 1
455 456
    if (err_flag == 0) {

457
      start_meas(dlsch_turbo_decoding_stats);
458
      ret = tc
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
            (&harq_process->d[r][96],
             harq_process->c[r],
             Kr,
             f1f2mat_old[iind*2],
             f1f2mat_old[(iind*2)+1],
             dlsch->max_turbo_iterations,
             crc_type,
             (r==0) ? harq_process->F : 0,
             &phy_vars_ue->dlsch_tc_init_stats,
             &phy_vars_ue->dlsch_tc_alpha_stats,
             &phy_vars_ue->dlsch_tc_beta_stats,
             &phy_vars_ue->dlsch_tc_gamma_stats,
             &phy_vars_ue->dlsch_tc_ext_stats,
             &phy_vars_ue->dlsch_tc_intl1_stats,
             &phy_vars_ue->dlsch_tc_intl2_stats); //(is_crnti==0)?harq_pid:harq_pid+1);


      stop_meas(dlsch_turbo_decoding_stats);
477
    }
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
#else
    if ((harq_process->C == 1) ||  
	((r==harq_process->C-1) && (skipped_last==0))) { // last segment with odd number of segments

      start_meas(dlsch_turbo_decoding_stats);
      ret = tc
            (&harq_process->d[r][96],
             harq_process->c[r],
             Kr,
             f1f2mat_old[iind*2],
             f1f2mat_old[(iind*2)+1],
             dlsch->max_turbo_iterations,
             crc_type,
             (r==0) ? harq_process->F : 0,
             &phy_vars_ue->dlsch_tc_init_stats,
             &phy_vars_ue->dlsch_tc_alpha_stats,
             &phy_vars_ue->dlsch_tc_beta_stats,
             &phy_vars_ue->dlsch_tc_gamma_stats,
             &phy_vars_ue->dlsch_tc_ext_stats,
             &phy_vars_ue->dlsch_tc_intl1_stats,
             &phy_vars_ue->dlsch_tc_intl2_stats); //(is_crnti==0)?harq_pid:harq_pid+1);
      stop_meas(dlsch_turbo_decoding_stats);
      //      printf("single decode, exit\n");
      //      exit(-1);
    }
    else {
    // we can merge code segments
      if ((skipped_last == 0) && (r<harq_process->C-1)) {
	skipped_last = 1;
	Kr_last = Kr;
      }
      else {
	skipped_last=0;
	
	if (Kr_last == Kr) { // decode 2 code segments with AVX2 version
#ifdef DEBUG_DLSCH_DECODING
	  printf("single decoding segment %d (%p)\n",r-1,&harq_process->d[r-1][96]);
#endif
	  start_meas(dlsch_turbo_decoding_stats);
#ifdef DEBUG_DLSCH_DECODING
	  printf("double decoding segments %d,%d (%p,%p)\n",r-1,r,&harq_process->d[r-1][96],&harq_process->d[r][96]);
#endif
	  ret = tc_2cw
            (&harq_process->d[r-1][96],
	     &harq_process->d[r][96],
             harq_process->c[r-1],
             harq_process->c[r],
             Kr,
             f1f2mat_old[iind*2],
             f1f2mat_old[(iind*2)+1],
             dlsch->max_turbo_iterations,
             crc_type,
             (r==0) ? harq_process->F : 0,
             &phy_vars_ue->dlsch_tc_init_stats,
             &phy_vars_ue->dlsch_tc_alpha_stats,
             &phy_vars_ue->dlsch_tc_beta_stats,
             &phy_vars_ue->dlsch_tc_gamma_stats,
             &phy_vars_ue->dlsch_tc_ext_stats,
             &phy_vars_ue->dlsch_tc_intl1_stats,
             &phy_vars_ue->dlsch_tc_intl2_stats); //(is_crnti==0)?harq_pid:harq_pid+1);
	  /*
	  ret = tc
            (&harq_process->d[r-1][96],
             harq_process->c[r-1],
             Kr_last,
             f1f2mat_old[iind*2],
             f1f2mat_old[(iind*2)+1],
             dlsch->max_turbo_iterations,
             crc_type,
             (r==0) ? harq_process->F : 0,
             &phy_vars_ue->dlsch_tc_init_stats,
             &phy_vars_ue->dlsch_tc_alpha_stats,
             &phy_vars_ue->dlsch_tc_beta_stats,
             &phy_vars_ue->dlsch_tc_gamma_stats,
             &phy_vars_ue->dlsch_tc_ext_stats,
             &phy_vars_ue->dlsch_tc_intl1_stats,
             &phy_vars_ue->dlsch_tc_intl2_stats); //(is_crnti==0)?harq_pid:harq_pid+1);
555

556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
	     exit(-1);*/
	  stop_meas(dlsch_turbo_decoding_stats);
	} 
	else { // Kr_last != Kr
	  start_meas(dlsch_turbo_decoding_stats);
	  ret = tc
            (&harq_process->d[r-1][96],
             harq_process->c[r-1],
             Kr_last,
             f1f2mat_old[iind*2],
             f1f2mat_old[(iind*2)+1],
             dlsch->max_turbo_iterations,
             crc_type,
             (r==0) ? harq_process->F : 0,
             &phy_vars_ue->dlsch_tc_init_stats,
             &phy_vars_ue->dlsch_tc_alpha_stats,
             &phy_vars_ue->dlsch_tc_beta_stats,
             &phy_vars_ue->dlsch_tc_gamma_stats,
             &phy_vars_ue->dlsch_tc_ext_stats,
             &phy_vars_ue->dlsch_tc_intl1_stats,
             &phy_vars_ue->dlsch_tc_intl2_stats); //(is_crnti==0)?harq_pid:harq_pid+1);
	  stop_meas(dlsch_turbo_decoding_stats);
	  
	  start_meas(dlsch_turbo_decoding_stats);
	  ret = tc
            (&harq_process->d[r][96],
             harq_process->c[r],
             Kr,
             f1f2mat_old[iind*2],
             f1f2mat_old[(iind*2)+1],
             dlsch->max_turbo_iterations,
             crc_type,
             (r==0) ? harq_process->F : 0,
             &phy_vars_ue->dlsch_tc_init_stats,
             &phy_vars_ue->dlsch_tc_alpha_stats,
             &phy_vars_ue->dlsch_tc_beta_stats,
             &phy_vars_ue->dlsch_tc_gamma_stats,
             &phy_vars_ue->dlsch_tc_ext_stats,
             &phy_vars_ue->dlsch_tc_intl1_stats,
             &phy_vars_ue->dlsch_tc_intl2_stats); //(is_crnti==0)?harq_pid:harq_pid+1);
	  stop_meas(dlsch_turbo_decoding_stats);
	  
	}
      }
    }
#endif
602

603

604
    if ((err_flag == 0) && (ret>=(1+dlsch->max_turbo_iterations))) {// a Code segment is in error so break;
605
      //printf("CRC failed, segment %d\n",r);
606 607 608 609 610 611 612 613 614
      err_flag = 1;
    }

  }

  if (err_flag == 1) {
    dlsch->harq_ack[subframe].ack = 0;
    dlsch->harq_ack[subframe].harq_id = harq_pid;
    dlsch->harq_ack[subframe].send_harq_status = 1;
615
    harq_process->errors[harq_process->round]++;
616
    harq_process->round++;
617

Raymond Knopp's avatar
Raymond Knopp committed
618 619
    //    LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round);
    //    printf("Rate: [UE %d] DLSCH: Setting NACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round);
620 621 622
    if (harq_process->round >= dlsch->Mdlharq) {
      harq_process->status = SCH_IDLE;
    }
623

624
    return((1+dlsch->max_turbo_iterations));
625
  } else {
626 627 628 629 630
    harq_process->status = SCH_IDLE;
    harq_process->round  = 0;
    dlsch->harq_ack[subframe].ack = 1;
    dlsch->harq_ack[subframe].harq_id = harq_pid;
    dlsch->harq_ack[subframe].send_harq_status = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
631 632
    LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round);

633
  }
634

635 636
  // Reassembly of Transport block here
  offset = 0;
637 638

  /*
639 640 641
  printf("harq_pid %d\n",harq_pid);
  printf("F %d, Fbytes %d\n",harq_process->F,harq_process->F>>3);
  printf("C %d\n",harq_process->C);
642
  */
643
  for (r=0; r<harq_process->C; r++) {
644 645 646 647 648 649
    if (r<harq_process->Cminus)
      Kr = harq_process->Kminus;
    else
      Kr = harq_process->Kplus;

    Kr_bytes = Kr>>3;
650

651 652 653
    //    printf("Segment %d : Kr= %d bytes\n",r,Kr_bytes);
    if (r==0) {
      memcpy(harq_process->b,
654 655
             &harq_process->c[0][(harq_process->F>>3)],
             Kr_bytes - (harq_process->F>>3)- ((harq_process->C>1)?3:0));
656
      offset = Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0);
657
      //            printf("copied %d bytes to b sequence (harq_pid %d)\n",
658
      //          Kr_bytes - (harq_process->F>>3),harq_pid);
659
      //          printf("b[0] = %x,c[%d] = %x\n",
660 661 662 663
      //      harq_process->b[0],
      //      harq_process->F>>3,
      //      harq_process->c[0][(harq_process->F>>3)]);
    } else {
664
      memcpy(harq_process->b+offset,
665 666
             harq_process->c[r],
             Kr_bytes- ((harq_process->C>1)?3:0));
667 668 669
      offset += (Kr_bytes - ((harq_process->C>1)?3:0));
    }
  }
670

671 672 673 674 675 676 677 678 679 680
  return(ret);
}

#ifdef PHY_ABSTRACTION
#include "SIMULATION/TOOLS/defs.h"
#ifdef OPENAIR2
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/defs.h"
#endif

681 682 683
int dlsch_abstraction_EESM(double* sinr_dB, uint8_t TM, uint32_t rb_alloc[4], uint8_t mcs, uint8_t dl_power_off)
{

684
  int ii;
685 686 687 688
  double sinr_eff = 0;
  int rb_count = 0;
  int offset;
  double bler = 0;
689 690 691 692

  if(TM==5 && dl_power_off==1) {
    //do nothing -- means there is no second UE and TM 5 is behaving like TM 6 for a singal user
  } else
693
    TM = TM-1;
694

695 696 697
  for (offset = 0; offset <= 24; offset++) {
    if (rb_alloc[0] & (1<<offset)) {
      rb_count++;
698 699 700 701 702 703 704 705

      for(ii=0; ii<12; ii++) {
        sinr_eff += exp(-(pow(10, 0.1*(sinr_dB[(offset*12)+ii])))/beta1_dlsch[TM][mcs]);
        //printf("sinr_eff1 = %f, power %lf\n",sinr_eff, exp(-pow(10,6.8)));

        //  sinr_eff += exp(-(pow(10, (sinr_dB[offset*2+1])/10))/beta1_dlsch[TM][mcs]);
        //printf("sinr_dB[%d]=%f\n",offset,sinr_dB[offset*2]);
      }
706
    }
707 708
  }

709
  LOG_D(OCM,"sinr_eff (lin, unweighted) = %f\n",sinr_eff);
710
  sinr_eff =  -beta2_dlsch[TM][mcs]*log((sinr_eff)/(12*rb_count));
711
  LOG_D(OCM,"sinr_eff (lin, weighted) = %f\n",sinr_eff);
712
  sinr_eff = 10 * log10(sinr_eff);
713
  LOG_D(OCM,"sinr_eff (dB) = %f\n",sinr_eff);
714

715
  bler = interp(sinr_eff,&sinr_bler_map[mcs][0][0],&sinr_bler_map[mcs][1][0],table_length[mcs]);
716

717
#ifdef USER_MODE // need to be adapted for the emulation in the kernel space 
718

719 720
  if (uniformrandom() < bler) {
    LOG_I(OCM,"abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f, TM %d)\n",mcs,sinr_eff,bler, TM);
721
    return(1);
722
  } else {
723
    LOG_I(OCM,"abstraction_decoding successful (mcs=%d, sinr_eff=%f, bler=%f, TM %d)\n",mcs,sinr_eff,bler, TM);
724 725
    return(1);
  }
726

727 728 729
#endif
}

730 731
int dlsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint32_t rb_alloc[4], uint8_t mcs,uint8_t dl_power_off)
{
732
  int ii;
733 734
  double sinr_eff = 0;
  double x = 0;
735
  double I =0;
736 737 738 739 740 741 742 743
  double qpsk_max=12.2;
  double qam16_max=19.2;
  double qam64_max=25.2;
  double sinr_min = -20;
  int rb_count = 0;
  int offset=0;
  double bler = 0;

744 745 746 747 748 749
  if(TM==5 && dl_power_off==1) {
    //do nothing -- means there is no second UE and TM 5 is behaving like TM 6 for a singal user
  } else
    TM = TM-1;


750 751 752
  for (offset = 0; offset <= 24; offset++) {
    if (rb_alloc[0] & (1<<offset)) {
      rb_count++;
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778

      for(ii=0; ii<12; ii++) {
        //x is the sinr_dB in dB
        x = sinr_dB[(offset*12)+ii] - 10*log10(beta1_dlsch_MI[TM][mcs]);

        if(x<sinr_min)
          I +=0;
        else {
          if(mcs<10) {
            if(x>qpsk_max)
              I += 1;
            else
              I += (q_qpsk[0]*pow(x,7) + q_qpsk[1]*pow(x,6) + q_qpsk[2]*pow(x,5) + q_qpsk[3]*pow(x,4) + q_qpsk[4]*pow(x,3) + q_qpsk[5]*pow(x,2) + q_qpsk[6]*x + q_qpsk[7]);
          } else if(mcs>9 && mcs<17) {
            if(x>qam16_max)
              I += 1;
            else
              I += (q_qam16[0]*pow(x,7) + q_qam16[1]*pow(x,6) + q_qam16[2]*pow(x,5) + q_qam16[3]*pow(x,4) + q_qam16[4]*pow(x,3) + q_qam16[5]*pow(x,2) + q_qam16[6]*x + q_qam16[7]);
          } else if(mcs>16 && mcs<23) {

            if(x>qam64_max)
              I += 1;
            else
              I += (q_qam64[0]*pow(x,7) + q_qam64[1]*pow(x,6) + q_qam64[2]*pow(x,5) + q_qam64[3]*pow(x,4) + q_qam64[4]*pow(x,3) + q_qam64[5]*pow(x,2) + q_qam64[6]*x + q_qam64[7]);
          }
        }
779 780 781
      }
    }
  }
782 783 784

  // averaging of accumulated MI
  I = I/(12*rb_count);
785
  //Now  I->SINR_effective Mapping
786 787 788 789 790 791 792 793 794 795

  if(mcs<10) {
    sinr_eff = (p_qpsk[0]*pow(I,7) + p_qpsk[1]*pow(I,6) + p_qpsk[2]*pow(I,5) + p_qpsk[3]*pow(I,4) + p_qpsk[4]*pow(I,3) + p_qpsk[5]*pow(I,2) + p_qpsk[6]*I + p_qpsk[7]);
  } else if(mcs>9 && mcs<17) {
    sinr_eff = (p_qam16[0]*pow(I,7) + p_qam16[1]*pow(I,6) + p_qam16[2]*pow(I,5) + p_qam16[3]*pow(I,4) + p_qam16[4]*pow(I,3) + p_qam16[5]*pow(I,2) + p_qam16[6]*I + p_qam16[7]);
  } else if(mcs>16 && mcs<23) {
    sinr_eff = (p_qam64[0]*pow(I,7) + p_qam64[1]*pow(I,6) + p_qam64[2]*pow(I,5) + p_qam64[3]*pow(I,4) + p_qam64[4]*pow(I,3) + p_qam64[5]*pow(I,2) + p_qam64[6]*I + p_qam64[7]);
  }

  //sinr_eff = sinr_eff + 10*log10(beta2_dlsch_MI[TM][mcs]);
796
  LOG_D(OCM,"SINR_Eff = %e\n",sinr_eff);
797

798
  bler = interp(sinr_eff,&sinr_bler_map[mcs][0][0],&sinr_bler_map[mcs][1][0],table_length[mcs]);
799

800
#ifdef USER_MODE // need to be adapted for the emulation in the kernel space 
801

802
  if (uniformrandom() < bler) {
803
    LOG_N(OCM,"abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler);
804
    return(0);
805
  } else {
806
    LOG_I(OCM,"abstraction_decoding successful (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler);
807 808
    return(1);
  }
809

810
#endif
811
}
812 813

uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue,
814 815 816 817
                             uint8_t subframe,
                             uint8_t dlsch_id,
                             uint8_t eNB_id)
{
818 819 820 821 822 823 824

  LTE_UE_DLSCH_t *dlsch_ue;
  LTE_eNB_DLSCH_t *dlsch_eNB;
  uint8_t harq_pid;
  uint32_t eNB_id2;
  uint32_t ue_id;
#ifdef DEBUG_DLSCH_DECODING
825
  uint16_t i;
826
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
827
  uint8_t CC_id = phy_vars_ue->CC_id;
828

829
  // may not be necessary for PMCH??
830
  for (eNB_id2=0; eNB_id2<NB_eNB_INST; eNB_id2++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
831
    if (PHY_vars_eNB_g[eNB_id2][CC_id]->lte_frame_parms.Nid_cell == phy_vars_ue->lte_frame_parms.Nid_cell)
832 833
      break;
  }
834

835 836
  if (eNB_id2==NB_eNB_INST) {
    LOG_E(PHY,"FATAL : Could not find attached eNB for DLSCH emulation !!!!\n");
837
    mac_xface->macphy_exit("Could not find attached eNB for DLSCH emulation");
838 839 840 841 842 843 844 845 846 847
  }

  LOG_D(PHY,"[UE] dlsch_decoding_emul : subframe %d, eNB_id %d, dlsch_id %d\n",subframe,eNB_id2,dlsch_id);

  //  printf("dlsch_eNB_ra->harq_processes[0] %p\n",PHY_vars_eNB_g[eNB_id]->dlsch_eNB_ra->harq_processes[0]);


  switch (dlsch_id) {
  case 0: // SI
    dlsch_ue = phy_vars_ue->dlsch_ue_SI[eNB_id];
Raymond Knopp's avatar
 
Raymond Knopp committed
848
    dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB_SI;
849
    //    printf("Doing SI: TBS %d\n",dlsch_ue->harq_processes[0]->TBS>>3);
850
    memcpy(dlsch_ue->harq_processes[0]->b,dlsch_eNB->harq_processes[0]->b,dlsch_ue->harq_processes[0]->TBS>>3);
851
#ifdef DEBUG_DLSCH_DECODING
852
    LOG_D(PHY,"SI Decoded\n");
853 854

    for (i=0; i<dlsch_ue->harq_processes[0]->TBS>>3; i++)
855
      LOG_T(PHY,"%x.",dlsch_eNB->harq_processes[0]->b[i]);
856

857 858 859 860
    LOG_T(PHY,"\n");
#endif
    return(1);
    break;
861

862 863
  case 1: // RA
    dlsch_ue  = phy_vars_ue->dlsch_ue_ra[eNB_id];
Raymond Knopp's avatar
 
Raymond Knopp committed
864
    dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB_ra;
865
    memcpy(dlsch_ue->harq_processes[0]->b,dlsch_eNB->harq_processes[0]->b,dlsch_ue->harq_processes[0]->TBS>>3);
866
#ifdef DEBUG_DLSCH_DECODING
867
    LOG_D(PHY,"RA Decoded\n");
868 869

    for (i=0; i<dlsch_ue->harq_processes[0]->TBS>>3; i++)
870
      LOG_T(PHY,"%x.",dlsch_eNB->harq_processes[0]->b[i]);
871

872 873 874 875
    LOG_T(PHY,"\n");
#endif
    return(1);
    break;
876

877 878 879
  case 2: // TB0
    dlsch_ue  = phy_vars_ue->dlsch_ue[eNB_id][0];
    harq_pid = dlsch_ue->current_harq_pid;
Raymond Knopp's avatar
 
Raymond Knopp committed
880
    ue_id= (uint32_t)find_ue((int16_t)phy_vars_ue->lte_ue_pdcch_vars[(uint32_t)eNB_id]->crnti,PHY_vars_eNB_g[eNB_id2][CC_id]);
881
    DevAssert( ue_id != (uint32_t)-1 );
Raymond Knopp's avatar
 
Raymond Knopp committed
882
    dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB[ue_id][0];
883 884

#ifdef DEBUG_DLSCH_DECODING
885 886

    for (i=0; i<dlsch_ue->harq_processes[harq_pid]->TBS>>3; i++)
887
      LOG_T(PHY,"%x.",dlsch_eNB->harq_processes[harq_pid]->b[i]);
888

889 890 891
    LOG_T(PHY,"\n current harq pid is %d ue id %d \n", harq_pid, ue_id);
#endif

892 893 894 895 896 897
    if (dlsch_abstraction_MIESM(phy_vars_ue->sinr_dB,
                                phy_vars_ue->transmission_mode[eNB_id],
                                dlsch_eNB->harq_processes[harq_pid]->rb_alloc,
                                dlsch_eNB->harq_processes[harq_pid]->mcs,
                                PHY_vars_eNB_g[eNB_id][CC_id]->mu_mimo_mode[ue_id].dl_pow_off) == 1) {
      // reset HARQ
898 899 900 901 902
      dlsch_ue->harq_processes[harq_pid]->status = SCH_IDLE;
      dlsch_ue->harq_processes[harq_pid]->round  = 0;
      dlsch_ue->harq_ack[subframe].ack = 1;
      dlsch_ue->harq_ack[subframe].harq_id = harq_pid;
      dlsch_ue->harq_ack[subframe].send_harq_status = 1;
903

904
      if (dlsch_ue->harq_processes[harq_pid]->round == 0)
905 906 907 908
        memcpy(dlsch_ue->harq_processes[harq_pid]->b,
               dlsch_eNB->harq_processes[harq_pid]->b,
               dlsch_ue->harq_processes[harq_pid]->TBS>>3);

909
      return(1);
910
    } else {
911 912 913 914 915 916 917
      // retransmission
      dlsch_ue->harq_processes[harq_pid]->status = ACTIVE;
      dlsch_ue->harq_processes[harq_pid]->round++;
      dlsch_ue->harq_ack[subframe].ack = 0;
      dlsch_ue->harq_ack[subframe].harq_id = harq_pid;
      dlsch_ue->harq_ack[subframe].send_harq_status = 1;
      return(1+dlsch_ue->max_turbo_iterations);
918
    }
919 920

    break;
921

922
  case 3: { // TB1
923 924
    dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id][1];
    harq_pid = dlsch_ue->current_harq_pid;
925 926 927
    int8_t UE_id = find_ue( phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti, PHY_vars_eNB_g[eNB_id2][CC_id] );
    DevAssert( UE_id != -1 );
    dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB[UE_id][1];
928
    // reset HARQ
929 930 931 932 933
    dlsch_ue->harq_processes[harq_pid]->status = SCH_IDLE;
    dlsch_ue->harq_processes[harq_pid]->round  = 0;
    dlsch_ue->harq_ack[subframe].ack = 1;
    dlsch_ue->harq_ack[subframe].harq_id = harq_pid;
    dlsch_ue->harq_ack[subframe].send_harq_status = 1;
934

935
    if (dlsch_ue->harq_processes[harq_pid]->round == 0)
936
      memcpy(dlsch_eNB->harq_processes[harq_pid]->b,dlsch_ue->harq_processes[harq_pid]->b,dlsch_ue->harq_processes[harq_pid]->TBS>>3);
937

938
    break;
939
  }
940

941
  case 5: // PMCH
942

943
    dlsch_ue  = phy_vars_ue->dlsch_ue_MCH[eNB_id];
Raymond Knopp's avatar
 
Raymond Knopp committed
944
    dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB_MCH;
945 946 947

    LOG_D(PHY,"decoding pmch emul (size is %d, enb %d %d)\n",  dlsch_ue->harq_processes[0]->TBS>>3, eNB_id, eNB_id2);
#ifdef DEBUG_DLSCH_DECODING
948 949

    for (i=0; i<dlsch_ue->harq_processes[0]->TBS>>3; i++)
950
      printf("%x.",dlsch_eNB->harq_processes[0]->b[i]);
951

952
    printf("\n");
953
#endif
954

955
    /*
956 957 958
      if (dlsch_abstraction_MIESM(phy_vars_ue->sinr_dB, phy_vars_ue->transmission_mode[eNB_id], dlsch_eNB->rb_alloc,
        dlsch_eNB->harq_processes[0]->mcs,PHY_vars_eNB_g[eNB_id]->mu_mimo_mode[ue_id].dl_pow_off) == 1) {
    */
959
    if (1) {
960
      // reset HARQ
961 962 963
      dlsch_ue->harq_processes[0]->status = SCH_IDLE;
      dlsch_ue->harq_processes[0]->round  = 0;
      memcpy(dlsch_ue->harq_processes[0]->b,
964 965
             dlsch_eNB->harq_processes[0]->b,
             dlsch_ue->harq_processes[0]->TBS>>3);
966
      return(1);
967
    } else {
968 969 970
      // retransmission
      return(1+dlsch_ue->max_turbo_iterations);
    }
971

972
    break;
973

974 975 976 977 978 979 980 981 982 983
  default:
    dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id][0];
    LOG_E(PHY,"dlsch_decoding_emul: FATAL, unknown DLSCH_id %d\n",dlsch_id);
    return(1+dlsch_ue->max_turbo_iterations);
  }

  LOG_E(PHY,"[FATAL] dlsch_decoding.c: Should never exit here ...\n");
  return(0);
}
#endif