dlsch_decoding.c 25.6 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
24
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@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"
knopp's avatar
   
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
85
LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag)
{
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
116
117
    dlsch->Kmimo = Kmimo;
    dlsch->Mdlharq = Mdlharq;
    dlsch->max_turbo_iterations = max_turbo_iterations;

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

122
      if (dlsch->harq_processes[i]) {
123
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
        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;
151
152
153
154
155
156
      }
    }

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

158
  msg("new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(LTE_DL_UE_HARQ_t), exit_flag);
159
160
161
162
163
164
165
166
167
168
169
170
171
  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,
172
173
174
175
                         uint8_t llr8_flag)
{


176
177
178
179
180
181
  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;
gauthier's avatar
gauthier committed
182
  uint16_t iind;
183
184
185
186
187
  //  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
gauthier's avatar
gauthier committed
188
  uint16_t i;
189
190
#endif
  uint8_t (*tc)(int16_t *y,
191
192
193
194
195
196
197
198
199
200
201
202
203
204
                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 *);
205
206
207
208
209
210
211

  if (!dlsch_llr) {
    msg("dlsch_decoding.c: NULL dlsch_llr pointer\n");
    return(dlsch->max_turbo_iterations);
  }

  if (!harq_process) {
212
213
    msg("dlsch_decoding.c: NULL harq_process pointer\n");
    return(dlsch->max_turbo_iterations);
214
215
216
  }

  if (!frame_parms) {
217
218
    msg("dlsch_decoding.c: NULL frame_parms pointer\n");
    return(dlsch->max_turbo_iterations);
219
  }
220

221
  if (subframe>9) {
222
223
    msg("dlsch_decoding.c: Illegal subframe index %d\n",subframe);
    return(dlsch->max_turbo_iterations);
224
225
226
227
228
229
  }

  if (llr8_flag == 0)
    tc = phy_threegpplte_turbo_decoder16;
  else
    tc = phy_threegpplte_turbo_decoder8;
230

231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  //  nb_rb = dlsch->nb_rb;

  /*
  if (nb_rb > frame_parms->N_RB_DL) {
    msg("dlsch_decoding.c: Illegal nb_rb %d\n",nb_rb);
    return(max_turbo_iterations);
    }*/

  /*harq_pid = dlsch->current_harq_pid;
  if (harq_pid >= 8) {
    msg("dlsch_decoding.c: Illegal harq_pid %d\n",harq_pid);
    return(max_turbo_iterations);
  }
  */
  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);

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

255
  if (harq_process->round == 0) {
256
257
258
    // This is a new packet, so compute quantities regarding segmentation
    harq_process->B = A+24;
    lte_segmentation(NULL,
259
260
261
262
263
264
265
266
                     NULL,
                     harq_process->B,
                     &harq_process->C,
                     &harq_process->Cplus,
                     &harq_process->Cminus,
                     &harq_process->Kplus,
                     &harq_process->Kminus,
                     &harq_process->F);
267
268
    //  CLEAR LLR's HERE for first packet in process
  }
269

270
271
272
273
274
275
276
277
  /*
  else {
    msg("dlsch_decoding.c: Ndi>0 not checked yet!!\n");
    return(max_turbo_iterations);
  }
  */
  err_flag = 0;
  r_offset = 0;
278

279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
  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;
  }

  if (harq_process->C >= MAX_NUM_DLSCH_SEGMENTS/bw_scaling) {
    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));
  }
303
  for (r=0; r<harq_process->C; r++) {
304

305
    
306
307
308
309
310
    // Get Turbo interleaver parameters
    if (r<harq_process->Cminus)
      Kr = harq_process->Kminus;
    else
      Kr = harq_process->Kplus;
311

312
    Kr_bytes = Kr>>3;
313

314
315
316
317
318
319
320
321
322
323
    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 {
      msg("dlsch_decoding: Illegal codeword size %d!!!\n",Kr_bytes);
324
      return(dlsch->max_turbo_iterations);
325
    }
326
327

#ifdef DEBUG_DLSCH_DECODING
328
329
330
331
332
    msg("f1 %d, f2 %d, F %d\n",f1f2mat_old[2*iind],f1f2mat_old[1+(2*iind)],(r==0) ? harq_process->F : 0);
#endif

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

337
#ifdef DEBUG_DLSCH_DECODING
knopp's avatar
   
knopp committed
338
    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",
339
340
341
          harq_pid,r, G,
          Kr*3,
          harq_process->TBS,
342
          harq_process->Qm,
343
344
345
346
347
          harq_process->nb_rb,
          harq_process->Nl,
          harq_process->rvidx,
          harq_process->round);
#endif
348
349
350


    if (lte_rate_matching_turbo_rx(harq_process->RTC[r],
351
352
353
354
355
356
357
358
359
360
                                   G,
                                   harq_process->w[r],
                                   (uint8_t*)&dummy_w[r][0],
                                   dlsch_llr+r_offset,
                                   harq_process->C,
                                   NSOFT,
                                   dlsch->Mdlharq,
                                   dlsch->Kmimo,
                                   harq_process->rvidx,
                                   (harq_process->round==0)?1:0,
361
                                   harq_process->Qm,
362
363
364
                                   harq_process->Nl,
                                   r,
                                   &E)==-1) {
365
366
367
      stop_meas(dlsch_rate_unmatching_stats);
      msg("dlsch_decoding.c: Problem in rate_matching\n");
      return(dlsch->max_turbo_iterations);
368
    } else
369
      stop_meas(dlsch_rate_unmatching_stats);
370

371
372
373
374
    r_offset += E;

    /*
    msg("Subblock deinterleaving, d %p w %p\n",
375
376
     harq_process->d[r],
     harq_process->w);
377
378
    */
    start_meas(dlsch_deinterleaving_stats);
379
380
    sub_block_deinterleaving_turbo(4+Kr,
                                   &harq_process->d[r][96],
381

382
                                   harq_process->w[r]);
383
    stop_meas(dlsch_deinterleaving_stats);
384
385

#ifdef DEBUG_DLSCH_DECODING
386
387
388
389
390
    /*
    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);
    }
391

392
393
394
395
396
    msg("decoder input(segment %d) :",r);
    int i; for (i=0;i<(3*8*Kr_bytes)+12;i++)
      msg("%d : %d\n",i,harq_process->d[r][96+i]);
      msg("\n");*/
#endif
397

398
399
400

    //    msg("Clearing c, %p\n",harq_process->c[r]);
    memset(harq_process->c[r],0,Kr_bytes);
401

402
    //    msg("done\n");
403
    if (harq_process->C == 1)
404
      crc_type = CRC24_A;
405
    else
406
407
      crc_type = CRC24_B;

408
    /*
409
410
    msg("decoder input(segment %d)\n",r);
    for (i=0;i<(3*8*Kr_bytes)+12;i++)
411
412
413
      if ((harq_process->d[r][96+i]>7) ||
    (harq_process->d[r][96+i] < -8))
    msg("%d : %d\n",i,harq_process->d[r][96+i]);
414
415
416
417
418
    msg("\n");
    */

    if (err_flag == 0) {

419
      start_meas(dlsch_turbo_decoding_stats);
420
421
422
#ifdef TURBO_S
      ret = phy_threegpplte_turbo_decoder_scalar
#else
423

424
425
      ret = tc
#endif
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
            (&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);
444
445
446
    }


447

448
449
450
451
452
453
454
455
456
457
458
459
    if ((err_flag == 0) && (ret>=(1+dlsch->max_turbo_iterations))) {// a Code segment is in error so break;
      //msg("CRC failed, segment %d\n",r);
      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;
    harq_process->round++;
460

knopp's avatar
knopp committed
461
462
    //    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);
463
464
465
    if (harq_process->round >= dlsch->Mdlharq) {
      harq_process->status = SCH_IDLE;
    }
466

467
    return((1+dlsch->max_turbo_iterations));
468
  } else {
469
470
471
472
473
    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;
knopp's avatar
   
knopp committed
474
475
    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);

476
  }
477

478
479
  // Reassembly of Transport block here
  offset = 0;
480
481

  /*
482
483
484
485
  msg("harq_pid %d\n",harq_pid);
  msg("F %d, Fbytes %d\n",harq_process->F,harq_process->F>>3);
  msg("C %d\n",harq_process->C);
  */
486
  for (r=0; r<harq_process->C; r++) {
487
488
489
490
491
492
    if (r<harq_process->Cminus)
      Kr = harq_process->Kminus;
    else
      Kr = harq_process->Kplus;

    Kr_bytes = Kr>>3;
493

494
495
496
    //    printf("Segment %d : Kr= %d bytes\n",r,Kr_bytes);
    if (r==0) {
      memcpy(harq_process->b,
497
498
             &harq_process->c[0][(harq_process->F>>3)],
             Kr_bytes - (harq_process->F>>3)- ((harq_process->C>1)?3:0));
499
500
      offset = Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0);
      //            msg("copied %d bytes to b sequence (harq_pid %d)\n",
501
502
503
504
505
506
      //          Kr_bytes - (harq_process->F>>3),harq_pid);
      //          msg("b[0] = %x,c[%d] = %x\n",
      //      harq_process->b[0],
      //      harq_process->F>>3,
      //      harq_process->c[0][(harq_process->F>>3)]);
    } else {
507
      memcpy(harq_process->b+offset,
508
509
             harq_process->c[r],
             Kr_bytes- ((harq_process->C>1)?3:0));
510
511
512
      offset += (Kr_bytes - ((harq_process->C>1)?3:0));
    }
  }
513

514
515
516
517
518
519
520
521
522
523
  return(ret);
}

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

524
525
526
int dlsch_abstraction_EESM(double* sinr_dB, uint8_t TM, uint32_t rb_alloc[4], uint8_t mcs, uint8_t dl_power_off)
{

527
  int ii;
528
529
530
531
  double sinr_eff = 0;
  int rb_count = 0;
  int offset;
  double bler = 0;
532
533
534
535

  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
536
    TM = TM-1;
537

538
539
540
  for (offset = 0; offset <= 24; offset++) {
    if (rb_alloc[0] & (1<<offset)) {
      rb_count++;
541
542
543
544
545
546
547
548

      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]);
      }
549
    }
550
551
  }

552
  LOG_D(OCM,"sinr_eff (lin, unweighted) = %f\n",sinr_eff);
553
  sinr_eff =  -beta2_dlsch[TM][mcs]*log((sinr_eff)/(12*rb_count));
554
  LOG_D(OCM,"sinr_eff (lin, weighted) = %f\n",sinr_eff);
555
  sinr_eff = 10 * log10(sinr_eff);
556
  LOG_D(OCM,"sinr_eff (dB) = %f\n",sinr_eff);
557

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

560
#ifdef USER_MODE // need to be adapted for the emulation in the kernel space 
561

562
563
  if (uniformrandom() < bler) {
    LOG_I(OCM,"abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f, TM %d)\n",mcs,sinr_eff,bler, TM);
564
    return(1);
565
  } else {
566
    LOG_I(OCM,"abstraction_decoding successful (mcs=%d, sinr_eff=%f, bler=%f, TM %d)\n",mcs,sinr_eff,bler, TM);
567
568
    return(1);
  }
569

570
571
572
#endif
}

573
574
int dlsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint32_t rb_alloc[4], uint8_t mcs,uint8_t dl_power_off)
{
575
  int ii;
576
577
  double sinr_eff = 0;
  double x = 0;
578
  double I =0;
579
580
581
582
583
584
585
586
  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;

587
588
589
590
591
592
  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;


593
594
595
  for (offset = 0; offset <= 24; offset++) {
    if (rb_alloc[0] & (1<<offset)) {
      rb_count++;
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621

      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]);
          }
        }
622
623
624
      }
    }
  }
625
626
627

  // averaging of accumulated MI
  I = I/(12*rb_count);
628
  //Now  I->SINR_effective Mapping
629
630
631
632
633
634
635
636
637
638

  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]);
639
  LOG_D(OCM,"SINR_Eff = %e\n",sinr_eff);
640

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

643
#ifdef USER_MODE // need to be adapted for the emulation in the kernel space 
644

645
  if (uniformrandom() < bler) {
646
    LOG_N(OCM,"abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler);
647
    return(0);
648
  } else {
649
    LOG_I(OCM,"abstraction_decoding successful (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler);
650
651
    return(1);
  }
652

653
#endif
654
}
655
656

uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue,
657
658
659
660
                             uint8_t subframe,
                             uint8_t dlsch_id,
                             uint8_t eNB_id)
{
661
662
663
664
665
666
667

  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
gauthier's avatar
gauthier committed
668
  uint16_t i;
669
#endif
knopp's avatar
   
knopp committed
670
  uint8_t CC_id = phy_vars_ue->CC_id;
671

672
  // may not be necessary for PMCH??
673
  for (eNB_id2=0; eNB_id2<NB_eNB_INST; eNB_id2++) {
knopp's avatar
   
knopp committed
674
    if (PHY_vars_eNB_g[eNB_id2][CC_id]->lte_frame_parms.Nid_cell == phy_vars_ue->lte_frame_parms.Nid_cell)
675
676
      break;
  }
677

678
679
  if (eNB_id2==NB_eNB_INST) {
    LOG_E(PHY,"FATAL : Could not find attached eNB for DLSCH emulation !!!!\n");
680
    mac_xface->macphy_exit("Could not find attached eNB for DLSCH emulation");
681
682
683
684
685
686
687
688
689
690
  }

  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];
knopp's avatar
   
knopp committed
691
    dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB_SI;
692
693
    //    msg("Doing SI: TBS %d\n",dlsch_ue->harq_processes[0]->TBS>>3);
    memcpy(dlsch_ue->harq_processes[0]->b,dlsch_eNB->harq_processes[0]->b,dlsch_ue->harq_processes[0]->TBS>>3);
694
#ifdef DEBUG_DLSCH_DECODING
695
    LOG_D(PHY,"SI Decoded\n");
696
697

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

700
701
702
703
    LOG_T(PHY,"\n");
#endif
    return(1);
    break;
704

705
706
  case 1: // RA
    dlsch_ue  = phy_vars_ue->dlsch_ue_ra[eNB_id];
knopp's avatar
   
knopp committed
707
    dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB_ra;
708
    memcpy(dlsch_ue->harq_processes[0]->b,dlsch_eNB->harq_processes[0]->b,dlsch_ue->harq_processes[0]->TBS>>3);
709
#ifdef DEBUG_DLSCH_DECODING
710
    LOG_D(PHY,"RA Decoded\n");
711
712

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

715
716
717
718
    LOG_T(PHY,"\n");
#endif
    return(1);
    break;
719

720
721
722
  case 2: // TB0
    dlsch_ue  = phy_vars_ue->dlsch_ue[eNB_id][0];
    harq_pid = dlsch_ue->current_harq_pid;
knopp's avatar
   
knopp committed
723
    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]);
724
    DevAssert( ue_id != (uint32_t)-1 );
knopp's avatar
   
knopp committed
725
    dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB[ue_id][0];
726
727

#ifdef DEBUG_DLSCH_DECODING
728
729

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

732
733
734
    LOG_T(PHY,"\n current harq pid is %d ue id %d \n", harq_pid, ue_id);
#endif

735
736
737
738
739
740
    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
741
742
743
744
745
      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;
746

747
      if (dlsch_ue->harq_processes[harq_pid]->round == 0)
748
749
750
751
        memcpy(dlsch_ue->harq_processes[harq_pid]->b,
               dlsch_eNB->harq_processes[harq_pid]->b,
               dlsch_ue->harq_processes[harq_pid]->TBS>>3);

752
      return(1);
753
    } else {
754
755
756
757
758
759
760
      // 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);
761
    }
762
763

    break;
764

765
  case 3: { // TB1
766
767
    dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id][1];
    harq_pid = dlsch_ue->current_harq_pid;
768
769
770
    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];
771
    // reset HARQ
772
773
774
775
776
    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;
777

778
    if (dlsch_ue->harq_processes[harq_pid]->round == 0)
779
      memcpy(dlsch_eNB->harq_processes[harq_pid]->b,dlsch_ue->harq_processes[harq_pid]->b,dlsch_ue->harq_processes[harq_pid]->TBS>>3);
780

781
    break;
782
  }
783

784
  case 5: // PMCH
785

786
    dlsch_ue  = phy_vars_ue->dlsch_ue_MCH[eNB_id];
knopp's avatar
   
knopp committed
787
    dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB_MCH;
788
789
790

    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
791
792

    for (i=0; i<dlsch_ue->harq_processes[0]->TBS>>3; i++)
nikaeinn's avatar
nikaeinn committed
793
      msg("%x.",dlsch_eNB->harq_processes[0]->b[i]);
794

nikaeinn's avatar
nikaeinn committed
795
    msg("\n");
796
#endif
797

798
    /*
799
800
801
      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) {
    */
802
    if (1) {
803
      // reset HARQ
804
805
806
      dlsch_ue->harq_processes[0]->status = SCH_IDLE;
      dlsch_ue->harq_processes[0]->round  = 0;
      memcpy(dlsch_ue->harq_processes[0]->b,
807
808
             dlsch_eNB->harq_processes[0]->b,
             dlsch_ue->harq_processes[0]->TBS>>3);
809
      return(1);
810
    } else {
811
812
813
      // retransmission
      return(1+dlsch_ue->max_turbo_iterations);
    }
814

815
    break;
816

817
818
819
820
821
822
823
824
825
826
  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