ulsch_decoding.c 42 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 23 24 25 26 27 28 29 30 31 32

/*! \file PHY/LTE_TRANSPORT/ulsch_decoding.c
* \brief Top-level routines for decoding  the ULSCH transport channel from 36.212 V8.6 2009-03
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/

33

Wang Tsu-Han's avatar
Wang Tsu-Han committed
34
#include <syscall.h>
35 36 37 38 39 40 41
#include "PHY/defs_eNB.h"
#include "PHY/phy_extern.h"
#include "PHY/CODING/coding_extern.h"
#include "SCHED/sched_eNB.h"
#include "LAYER2/MAC/mac.h"
#include "RRC/LTE/rrc_extern.h"
#include "PHY_INTERFACE/phy_interface.h"
42

43
#include "common/utils/LOG/vcd_signal_dumper.h"
44
//#define DEBUG_ULSCH_DECODING
45
#include "targets/RT/USER/rt_wrapper.h"
46
#include "transport_proto.h"
47

48
extern WORKER_CONF_t get_thread_worker_conf(void);
49

frtabu's avatar
frtabu committed
50
void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch) {
51 52 53
  int i,r;

  if (ulsch) {
54
    for (i=0; i<8; i++) {
55
      if (ulsch->harq_processes[i]) {
56 57 58 59 60 61
        if (ulsch->harq_processes[i]->b) {
          free16(ulsch->harq_processes[i]->b,MAX_ULSCH_PAYLOAD_BYTES);
          ulsch->harq_processes[i]->b = NULL;
        }

        for (r=0; r<MAX_NUM_ULSCH_SEGMENTS; r++) {
62 63 64
          free16(ulsch->harq_processes[i]->c[r],((r==0)?8:0) + 768);
          ulsch->harq_processes[i]->c[r] = NULL;
        }
65 66 67 68 69 70 71 72 73

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

        free16(ulsch->harq_processes[i],sizeof(LTE_UL_eNB_HARQ_t));
        ulsch->harq_processes[i] = NULL;
74 75
      }
    }
76 77

    free16(ulsch,sizeof(LTE_eNB_ULSCH_t));
78 79 80
  }
}

frtabu's avatar
frtabu committed
81
LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag) {
82 83 84
  LTE_eNB_ULSCH_t *ulsch;
  uint8_t exit_flag = 0,i,r;
  unsigned char bw_scaling =1;
85 86

  switch (N_RB_UL) {
frtabu's avatar
frtabu committed
87 88 89
    case 6:
      bw_scaling =16;
      break;
90

frtabu's avatar
frtabu committed
91 92 93
    case 25:
      bw_scaling =4;
      break;
94

frtabu's avatar
frtabu committed
95 96 97
    case 50:
      bw_scaling =2;
      break;
98

frtabu's avatar
frtabu committed
99 100 101
    default:
      bw_scaling =1;
      break;
102
  }
103

104
  ulsch = (LTE_eNB_ULSCH_t *)malloc16(sizeof(LTE_eNB_ULSCH_t));
105

106
  if (ulsch) {
107
    memset(ulsch,0,sizeof(LTE_eNB_ULSCH_t));
108
    ulsch->max_turbo_iterations = max_turbo_iterations;
109
    ulsch->Mlimit = 4;
110

111
    for (i=0; i<8; i++) {
Raymond Knopp's avatar
Raymond Knopp committed
112
      //      printf("new_ue_ulsch: Harq process %d\n",i);
113
      ulsch->harq_processes[i] = (LTE_UL_eNB_HARQ_t *)malloc16(sizeof(LTE_UL_eNB_HARQ_t));
114

115
      if (ulsch->harq_processes[i]) {
116
        memset(ulsch->harq_processes[i],0,sizeof(LTE_UL_eNB_HARQ_t));
frtabu's avatar
frtabu committed
117
        ulsch->harq_processes[i]->b = (uint8_t *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling);
118 119 120 121 122 123 124 125

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

        if (abstraction_flag==0) {
          for (r=0; r<MAX_NUM_ULSCH_SEGMENTS/bw_scaling; r++) {
frtabu's avatar
frtabu committed
126 127
            ulsch->harq_processes[i]->c[r] = (uint8_t *)malloc16(((r==0)?8:0) + 3+768);

128 129 130 131 132
            if (ulsch->harq_processes[i]->c[r])
              memset(ulsch->harq_processes[i]->c[r],0,((r==0)?8:0) + 3+768);
            else
              exit_flag=2;

frtabu's avatar
frtabu committed
133
            ulsch->harq_processes[i]->d[r] = (short *)malloc16(((3*8*6144)+12+96)*sizeof(short));
134 135 136 137 138 139 140 141 142

            if (ulsch->harq_processes[i]->d[r])
              memset(ulsch->harq_processes[i]->d[r],0,((3*8*6144)+12+96)*sizeof(short));
            else
              exit_flag=2;
          }
        }
      } else {
        exit_flag=1;
143 144 145 146 147 148
      }
    }

    if (exit_flag==0)
      return(ulsch);
  }
149

150 151 152 153 154
  LOG_E(PHY,"new_ue_ulsch: exit_flag = %d\n",exit_flag);
  free_eNB_ulsch(ulsch);
  return(NULL);
}

frtabu's avatar
frtabu committed
155
void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch) {
156 157 158 159 160
  unsigned char i;

  //ulsch = (LTE_eNB_ULSCH_t *)malloc16(sizeof(LTE_eNB_ULSCH_t));
  if (ulsch) {
    ulsch->rnti = 0;
161
    ulsch->harq_mask = 0;
162

163
    for (i=0; i<8; i++) {
164
      if (ulsch->harq_processes[i]) {
165 166 167 168 169
        //    ulsch->harq_processes[i]->Ndi = 0;
        ulsch->harq_processes[i]->status = 0;
        //ulsch->harq_processes[i]->phich_active = 0; //this will be done later after transmission of PHICH
        ulsch->harq_processes[i]->phich_ACK = 0;
        ulsch->harq_processes[i]->round = 0;
170 171 172 173 174 175
        ulsch->harq_processes[i]->rar_alloc = 0;
        ulsch->harq_processes[i]->first_rb = 0;
        ulsch->harq_processes[i]->nb_rb = 0;
        ulsch->harq_processes[i]->TBS = 0;
        ulsch->harq_processes[i]->Or1 = 0;
        ulsch->harq_processes[i]->Or2 = 0;
frtabu's avatar
frtabu committed
176

177 178 179
        for ( int j = 0; j < 2; j++ ) {
          ulsch->harq_processes[i]->o_RI[j] = 0;
        }
frtabu's avatar
frtabu committed
180

181 182 183 184 185
        ulsch->harq_processes[i]->O_ACK = 0;
        ulsch->harq_processes[i]->srs_active = 0;
        ulsch->harq_processes[i]->rvidx = 0;
        ulsch->harq_processes[i]->Msc_initial = 0;
        ulsch->harq_processes[i]->Nsymb_initial = 0;
186 187
      }
    }
frtabu's avatar
frtabu committed
188

189 190 191 192
    ulsch->beta_offset_cqi_times8 = 0;
    ulsch->beta_offset_ri_times8 = 0;
    ulsch->beta_offset_harqack_times8 = 0;
    ulsch->Msg3_active = 0;
193 194 195 196
  }
}


frtabu's avatar
frtabu committed
197
uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH) {
198 199
  uint8_t crc;
  crc = cqi[CQI_LENGTH>>3];
Raymond Knopp's avatar
Raymond Knopp committed
200
  //  printf("crc1: %x, shift %d\n",crc,CQI_LENGTH&0x7);
201 202 203
  crc = (crc<<(CQI_LENGTH&0x7));
  // clear crc bits
  //  ((char *)cqi)[CQI_LENGTH>>3] &= 0xff>>(8-(CQI_LENGTH&0x7));
Raymond Knopp's avatar
Raymond Knopp committed
204
  //  printf("crc2: %x, cqi0 %x\n",crc,cqi[1+(CQI_LENGTH>>3)]);
205 206 207 208 209 210 211 212 213
  crc |= (cqi[1+(CQI_LENGTH>>3)])>>(8-(CQI_LENGTH&0x7));
  // clear crc bits
  //(((char *)cqi)[1+(CQI_LENGTH>>3)]) = 0;
  //  printf("crc : %x\n",crc);
  return(crc);
}



214

frtabu's avatar
frtabu committed
215
int ulsch_decoding_data_2thread0(td_params *tdp) {
216 217 218 219
  PHY_VARS_eNB *eNB = tdp->eNB;
  int UE_id         = tdp->UE_id;
  int harq_pid      = tdp->harq_pid;
  int llr8_flag     = tdp->llr8_flag;
220
  unsigned int r,r_offset=0,Kr,Kr_bytes;
221 222 223 224 225 226
  uint8_t crc_type;
  int offset = 0;
  int ret = 1;
  int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)];
  LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id];
  LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid];
227
  int Q_m = ulsch_harq->Qm;
228
  int G = ulsch_harq->G;
Raymond Knopp's avatar
Raymond Knopp committed
229
  uint32_t E=0;
230 231
  uint32_t Gp,GpmodC,Nl=1;
  uint32_t C = ulsch_harq->C;
232
  decoder_if_t *tc;
233 234

  if (llr8_flag == 0)
235
    tc = decoder16;
236
  else
237
    tc = decoder8;
238 239 240 241 242 243 244 245 246 247 248 249 250

  // go through first half of segments to get r_offset
  for (r=0; r<(ulsch_harq->C/2); r++) {
    // Get Turbo interleaver parameters
    if (r<ulsch_harq->Cminus)
      Kr = ulsch_harq->Kminus;
    else
      Kr = ulsch_harq->Kplus;

    Kr_bytes = Kr>>3;
    // This is stolen from rate-matching algorithm to get the value of E
    Gp = G/Nl/Q_m;
    GpmodC = Gp%C;
frtabu's avatar
frtabu committed
251

252 253 254 255
    if (r < (C-(GpmodC)))
      E = Nl*Q_m * (Gp/C);
    else
      E = Nl*Q_m * ((GpmodC==0?0:1) + (Gp/C));
frtabu's avatar
frtabu committed
256

257
    r_offset += E;
258 259 260 261 262 263

    if (r==0) {
      offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0);
    } else {
      offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0));
    }
264 265 266
  }

  // go through second half of segments
267
  for (; r<(ulsch_harq->C); r++) {
268 269 270 271 272 273 274 275 276 277
    //    printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]);
    // Get Turbo interleaver parameters
    if (r<ulsch_harq->Cminus)
      Kr = ulsch_harq->Kminus;
    else
      Kr = ulsch_harq->Kplus;

    Kr_bytes = Kr>>3;
    memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short));
    ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8),
frtabu's avatar
frtabu committed
278
                                          (uint8_t *)&dummy_w[r][0],
279 280
                                          (r==0) ? ulsch_harq->F : 0);
#ifdef DEBUG_ULSCH_DECODING
frtabu's avatar
frtabu committed
281 282 283 284 285 286
    printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, nb_rb %d, Nl %d)...\n",
           r, G,
           Kr*3,
           Q_m,
           nb_rb,
           ulsch_harq->Nl);
287 288 289 290 291
#endif

    if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r],
                                   G,
                                   ulsch_harq->w[r],
frtabu's avatar
frtabu committed
292
                                   (uint8_t *) &dummy_w[r][0],
293 294 295 296 297 298 299
                                   ulsch_harq->e+r_offset,
                                   ulsch_harq->C,
                                   NSOFT,
                                   0,   //Uplink
                                   1,
                                   ulsch_harq->rvidx,
                                   (ulsch_harq->round==0)?1:0,  // clear
300
                                   ulsch_harq->Qm,
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
                                   1,
                                   r,
                                   &E)==-1) {
      LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n");
      return(-1);
    }

    r_offset += E;
    sub_block_deinterleaving_turbo(4+Kr,
                                   &ulsch_harq->d[r][96],
                                   ulsch_harq->w[r]);

    if (ulsch_harq->C == 1)
      crc_type = CRC24_A;
    else
      crc_type = CRC24_B;
frtabu's avatar
frtabu committed
317

318
    ret = tc(&ulsch_harq->d[r][96],
319
             NULL,
frtabu's avatar
frtabu committed
320
             ulsch_harq->c[r],
321
             NULL,
frtabu's avatar
frtabu committed
322 323 324 325 326 327 328 329 330 331 332 333
             Kr,
             ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS,
             crc_type,
             (r==0) ? ulsch_harq->F : 0,
             &eNB->ulsch_tc_init_stats,
             &eNB->ulsch_tc_alpha_stats,
             &eNB->ulsch_tc_beta_stats,
             &eNB->ulsch_tc_gamma_stats,
             &eNB->ulsch_tc_ext_stats,
             &eNB->ulsch_tc_intl1_stats,
             &eNB->ulsch_tc_intl2_stats);

334
    // Reassembly of Transport block here
335 336 337

    if (ret != (1+ulsch->max_turbo_iterations)) {
      if (r<ulsch_harq->Cminus)
frtabu's avatar
frtabu committed
338
        Kr = ulsch_harq->Kminus;
339
      else
frtabu's avatar
frtabu committed
340 341
        Kr = ulsch_harq->Kplus;

342
      Kr_bytes = Kr>>3;
343
      memcpy(ulsch_harq->b+offset,
frtabu's avatar
frtabu committed
344 345
             ulsch_harq->c[r],
             Kr_bytes - ((ulsch_harq->C>1)?3:0));
346
      offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0));
347 348 349 350 351 352 353 354 355 356
    } else {
      break;
    }
  }

  return(ret);
}

extern int oai_exit;
void *td_thread(void *param) {
frtabu's avatar
frtabu committed
357
  PHY_VARS_eNB *eNB = ((td_params *)param)->eNB;
358
  L1_proc_t *proc  = &eNB->proc;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
359 360 361
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
  thread_top_init("td_thread",1,200000,250000,500000);
362 363
  pthread_setname_np( pthread_self(),"td processing");
  LOG_I(PHY,"thread td created id=%ld\n", syscall(__NR_gettid));
364
  //wait_sync("td_thread");
365 366

  while (!oai_exit) {
frtabu's avatar
frtabu committed
367
    if (wait_on_condition(&proc->mutex_td,&proc->cond_td,&proc->instance_cnt_td,"td thread")<0) break;
368

Wang Tsu-Han's avatar
Wang Tsu-Han committed
369
    if(oai_exit) break;
370

frtabu's avatar
frtabu committed
371
    ((td_params *)param)->ret = ulsch_decoding_data_2thread0((td_params *)param);
372 373 374 375 376 377 378 379 380 381 382 383 384 385

    if (release_thread(&proc->mutex_td,&proc->instance_cnt_td,"td thread")<0) break;

    if (pthread_cond_signal(&proc->cond_td) != 0) {
      printf("[eNB] ERROR pthread_cond_signal for td thread exit\n");
      exit_fun( "ERROR pthread_cond_signal" );
      return(NULL);
    }
  }

  return(NULL);
}

int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) {
386
  L1_proc_t *proc = &eNB->proc;
387
  unsigned int r,r_offset=0,Kr,Kr_bytes;
388 389 390 391 392 393
  uint8_t crc_type;
  int offset = 0;
  int ret = 1;
  int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)];
  LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id];
  LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid];
394
  int G = ulsch_harq->G;
395
  unsigned int E;
396
  int Cby2;
397
  decoder_if_t *tc;
398 399 400 401 402
  struct timespec wait;
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;

  if (llr8_flag == 0)
403
    tc = decoder16;
404
  else
405
    tc = decoder8;
406

407 408 409 410 411 412
  if (ulsch_harq->C>1) { // wakeup worker if more than 1 segment
    if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) {
      printf("[eNB] ERROR pthread_mutex_lock for TD thread (IC %d)\n", proc->instance_cnt_td);
      exit_fun( "error locking mutex_fep" );
      return -1;
    }
frtabu's avatar
frtabu committed
413

414 415 416 417 418 419
    if (proc->instance_cnt_td==0) {
      printf("[eNB] TD thread busy\n");
      exit_fun("TD thread busy");
      pthread_mutex_unlock( &proc->mutex_td );
      return -1;
    }
frtabu's avatar
frtabu committed
420

421 422 423 424 425
    ++proc->instance_cnt_td;
    proc->tdp.eNB       = eNB;
    proc->tdp.UE_id     = UE_id;
    proc->tdp.harq_pid  = harq_pid;
    proc->tdp.llr8_flag = llr8_flag;
frtabu's avatar
frtabu committed
426 427

    // wakeup worker to do second half segments
428 429 430 431 432
    if (pthread_cond_signal(&proc->cond_td) != 0) {
      printf("[eNB] ERROR pthread_cond_signal for td thread exit\n");
      exit_fun( "ERROR pthread_cond_signal" );
      return (1+ulsch->max_turbo_iterations);
    }
433 434

    pthread_mutex_unlock( &proc->mutex_td );
435
    Cby2 = ulsch_harq->C/2;
frtabu's avatar
frtabu committed
436
  } else {
437
    Cby2 = 1;
438 439 440
  }

  // go through first half of segments in main thread
441
  for (r=0; r<Cby2; r++) {
442 443 444 445 446 447 448 449 450 451
    //    printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]);
    // Get Turbo interleaver parameters
    if (r<ulsch_harq->Cminus)
      Kr = ulsch_harq->Kminus;
    else
      Kr = ulsch_harq->Kplus;

    Kr_bytes = Kr>>3;
    memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short));
    ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8),
frtabu's avatar
frtabu committed
452
                                          (uint8_t *)&dummy_w[r][0],
453 454
                                          (r==0) ? ulsch_harq->F : 0);
#ifdef DEBUG_ULSCH_DECODING
frtabu's avatar
frtabu committed
455 456 457 458 459 460
    printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, nb_rb %d, Nl %d)...\n",
           r, G,
           Kr*3,
           Q_m,
           nb_rb,
           ulsch_harq->Nl);
461 462 463 464 465 466
#endif
    start_meas(&eNB->ulsch_rate_unmatching_stats);

    if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r],
                                   G,
                                   ulsch_harq->w[r],
frtabu's avatar
frtabu committed
467
                                   (uint8_t *) &dummy_w[r][0],
468 469 470 471 472 473 474
                                   ulsch_harq->e+r_offset,
                                   ulsch_harq->C,
                                   NSOFT,
                                   0,   //Uplink
                                   1,
                                   ulsch_harq->rvidx,
                                   (ulsch_harq->round==0)?1:0,  // clear
475
                                   ulsch_harq->Qm,
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
                                   1,
                                   r,
                                   &E)==-1) {
      LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n");
      return(-1);
    }

    stop_meas(&eNB->ulsch_rate_unmatching_stats);
    r_offset += E;
    start_meas(&eNB->ulsch_deinterleaving_stats);
    sub_block_deinterleaving_turbo(4+Kr,
                                   &ulsch_harq->d[r][96],
                                   ulsch_harq->w[r]);
    stop_meas(&eNB->ulsch_deinterleaving_stats);

    if (ulsch_harq->C == 1)
      crc_type = CRC24_A;
    else
      crc_type = CRC24_B;

    start_meas(&eNB->ulsch_turbo_decoding_stats);
    ret = tc(&ulsch_harq->d[r][96],
498
             NULL,
frtabu's avatar
frtabu committed
499
             ulsch_harq->c[r],
500
             NULL,
frtabu's avatar
frtabu committed
501 502 503 504 505 506 507 508 509 510 511 512 513
             Kr,
             ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS,
             crc_type,
             (r==0) ? ulsch_harq->F : 0,
             &eNB->ulsch_tc_init_stats,
             &eNB->ulsch_tc_alpha_stats,
             &eNB->ulsch_tc_beta_stats,
             &eNB->ulsch_tc_gamma_stats,
             &eNB->ulsch_tc_ext_stats,
             &eNB->ulsch_tc_intl1_stats,
             &eNB->ulsch_tc_intl2_stats);

    // Reassembly of Transport block here
514 515 516

    if (ret != (1+ulsch->max_turbo_iterations)) {
      if (r<ulsch_harq->Cminus)
frtabu's avatar
frtabu committed
517
        Kr = ulsch_harq->Kminus;
518
      else
frtabu's avatar
frtabu committed
519 520
        Kr = ulsch_harq->Kplus;

521
      Kr_bytes = Kr>>3;
frtabu's avatar
frtabu committed
522

523
      if (r==0) {
frtabu's avatar
frtabu committed
524 525 526 527
        memcpy(ulsch_harq->b,
               &ulsch_harq->c[0][(ulsch_harq->F>>3)],
               Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0));
        offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0);
528
      } else {
frtabu's avatar
frtabu committed
529 530 531 532
        memcpy(ulsch_harq->b+offset,
               ulsch_harq->c[r],
               Kr_bytes - ((ulsch_harq->C>1)?3:0));
        offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0));
533 534 535 536 537
      }
    } else {
      break;
    }

frtabu's avatar
frtabu committed
538 539 540
    stop_meas(&eNB->ulsch_turbo_decoding_stats);
    //printf("/////////////////////////////////////////**************************loop for %d time in ulsch_decoding main\n",r);
  }
541

frtabu's avatar
frtabu committed
542 543
  // wait for worker to finish
  wait_on_busy_condition(&proc->mutex_td,&proc->cond_td,&proc->instance_cnt_td,"td thread");
544 545 546 547
  return( (ret>proc->tdp.ret) ? ret : proc->tdp.ret );
}

int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) {
548
  unsigned int r,r_offset=0,Kr,Kr_bytes;
549 550 551 552 553 554
  uint8_t crc_type;
  int offset = 0;
  int ret = 1;
  int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)];
  LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id];
  LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid];
555
  int G = ulsch_harq->G;
556
  unsigned int E;
557
  decoder_if_t *tc;
558 559
  static int32_t pusch_rep_buffer[3*(6144+64)];
  int max_Ncb;
560 561

  if (llr8_flag == 0)
562
    tc = *decoder16;
563
  else
564
    tc = *decoder8;
565

laurent's avatar
laurent committed
566 567
  if(ulsch_harq->repetition_number == 1) {
    memset(pusch_rep_buffer,0,(sizeof(int32_t)*3*(6144+64))) ;  // reset the buffer every new repetitions
568 569
  }

570 571 572 573 574 575 576 577 578 579 580
  for (r=0; r<ulsch_harq->C; r++) {
    //    printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]);
    // Get Turbo interleaver parameters
    if (r<ulsch_harq->Cminus)
      Kr = ulsch_harq->Kminus;
    else
      Kr = ulsch_harq->Kplus;

    Kr_bytes = Kr>>3;
    memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short));
    ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8),
frtabu's avatar
frtabu committed
581
                                          (uint8_t *)&dummy_w[r][0],
582 583
                                          (r==0) ? ulsch_harq->F : 0);
#ifdef DEBUG_ULSCH_DECODING
frtabu's avatar
frtabu committed
584 585 586
    printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, nb_rb %d, Nl %d)...\n",
           r, G,
           Kr*3,
laurent's avatar
laurent committed
587
           ulsch_harq->Qm,
frtabu's avatar
frtabu committed
588
           ulsch_harq->Nl);
589 590
#endif
    start_meas(&eNB->ulsch_rate_unmatching_stats);
Raymond Knopp's avatar
Raymond Knopp committed
591

592 593 594
    if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r],
                                   G,
                                   ulsch_harq->w[r],
frtabu's avatar
frtabu committed
595
                                   (uint8_t *) &dummy_w[r][0],
596 597 598 599 600 601
                                   ulsch_harq->e+r_offset,
                                   ulsch_harq->C,
                                   NSOFT,
                                   0,   //Uplink
                                   1,
                                   ulsch_harq->rvidx,
602
                                   (ulsch_harq->rvidx==0)?1:0,  // clear
603
                                   ulsch_harq->Qm,
604 605 606 607 608 609
                                   1,
                                   r,
                                   &E)==-1) {
      LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n");
      return(-1);
    }
Raymond Knopp's avatar
Raymond Knopp committed
610

611
    stop_meas(&eNB->ulsch_rate_unmatching_stats);
612 613
    max_Ncb = 3*ulsch_harq->RTC[r]*32 ;

laurent's avatar
laurent committed
614 615 616 617 618 619 620 621 622 623 624
    if(ulsch_harq->total_number_of_repetitions > 1) {
      if (ulsch_harq->rvidx==1) {
        // Store the result of HARQ combining in the last emtc repetitions of sequence 0,2,3,1
        for (int nn=0; nn<max_Ncb; nn++) {
          pusch_rep_buffer[nn] += ulsch_harq->w[r][nn] ;
        }
      }

      if (ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions) {
        for (int nn=0; nn<max_Ncb; nn++) {
          ulsch_harq->w[r][nn] =  pusch_rep_buffer[nn] ;
625 626
        }
      }
laurent's avatar
laurent committed
627
    }
628

629 630 631 632 633 634
    r_offset += E;
    start_meas(&eNB->ulsch_deinterleaving_stats);
    sub_block_deinterleaving_turbo(4+Kr,
                                   &ulsch_harq->d[r][96],
                                   ulsch_harq->w[r]);
    stop_meas(&eNB->ulsch_deinterleaving_stats);
Raymond Knopp's avatar
Raymond Knopp committed
635

636 637 638 639
    if (ulsch_harq->C == 1)
      crc_type = CRC24_A;
    else
      crc_type = CRC24_B;
frtabu's avatar
frtabu committed
640

641
    start_meas(&eNB->ulsch_turbo_decoding_stats);
Raymond Knopp's avatar
Raymond Knopp committed
642
    ret = tc(&ulsch_harq->d[r][96],
643
             NULL,
frtabu's avatar
frtabu committed
644
             ulsch_harq->c[r],
645
             NULL,
frtabu's avatar
frtabu committed
646 647 648 649 650 651 652 653 654 655 656
             Kr,
             ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS,
             crc_type,
             (r==0) ? ulsch_harq->F : 0,
             &eNB->ulsch_tc_init_stats,
             &eNB->ulsch_tc_alpha_stats,
             &eNB->ulsch_tc_beta_stats,
             &eNB->ulsch_tc_gamma_stats,
             &eNB->ulsch_tc_ext_stats,
             &eNB->ulsch_tc_intl1_stats,
             &eNB->ulsch_tc_intl2_stats);
Raymond Knopp's avatar
Raymond Knopp committed
657
    stop_meas(&eNB->ulsch_turbo_decoding_stats);
frtabu's avatar
frtabu committed
658 659

    // Reassembly of Transport block here
Raymond Knopp's avatar
Raymond Knopp committed
660

661 662
    if (ret != (1+ulsch->max_turbo_iterations)) {
      if (r<ulsch_harq->Cminus)
frtabu's avatar
frtabu committed
663
        Kr = ulsch_harq->Kminus;
664
      else
frtabu's avatar
frtabu committed
665 666
        Kr = ulsch_harq->Kplus;

667
      Kr_bytes = Kr>>3;
frtabu's avatar
frtabu committed
668

669
      if (r==0) {
frtabu's avatar
frtabu committed
670 671 672 673
        memcpy(ulsch_harq->b,
               &ulsch_harq->c[0][(ulsch_harq->F>>3)],
               Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0));
        offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0);
674
      } else {
frtabu's avatar
frtabu committed
675 676 677 678
        memcpy(ulsch_harq->b+offset,
               ulsch_harq->c[r],
               Kr_bytes - ((ulsch_harq->C>1)?3:0));
        offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0));
679 680 681
      }
    } else {
      break;
Raymond Knopp's avatar
Raymond Knopp committed
682 683 684
    }
  }

685 686 687
  return(ret);
}

frtabu's avatar
frtabu committed
688
int ulsch_decoding_data_all(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) {
689
  int ret = 0;
690
  /*if(get_thread_worker_conf() == WORKER_ENABLE)
691 692 693
  {
    ret = ulsch_decoding_data_2thread(eNB,UE_id,harq_pid,llr8_flag);
  }
694
  else*/
695 696 697 698 699 700
  {
    ret = ulsch_decoding_data(eNB,UE_id,harq_pid,llr8_flag);
  }
  return ret;
}

701
static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, unsigned char reset) __attribute__((always_inline));
frtabu's avatar
frtabu committed
702
static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, unsigned char reset) {
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
  int n;

  if (reset) {
    *x1 = 1+ (1<<31);
    *x2=*x2 ^ ((*x2 ^ (*x2>>1) ^ (*x2>>2) ^ (*x2>>3))<<31);

    // skip first 50 double words (1600 bits)
    //      printf("n=0 : x1 %x, x2 %x\n",x1,x2);
    for (n=1; n<50; n++) {
      *x1 = (*x1>>1) ^ (*x1>>4);
      *x1 = *x1 ^ (*x1<<31) ^ (*x1<<28);
      *x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4);
      *x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28);
    }
  }
718

719 720 721 722 723 724
  *x1 = (*x1>>1) ^ (*x1>>4);
  *x1 = *x1 ^ (*x1<<31) ^ (*x1<<28);
  *x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4);
  *x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28);
  return(*x1^*x2);
  //  printf("n=%d : c %x\n",n,x1^x2);
Raymond Knopp's avatar
Raymond Knopp committed
725
}
frtabu's avatar
frtabu committed
726

727
unsigned int  ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,
728 729 730
                             uint8_t UE_id,
                             uint8_t control_only_flag,
                             uint8_t Nbundled,
frtabu's avatar
frtabu committed
731
                             uint8_t llr8_flag) {
732 733 734
  int16_t *ulsch_llr = eNB->pusch_vars[UE_id]->llr;
  LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
  LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id];
735 736
  uint8_t harq_pid;
  unsigned short nb_rb;
737
  unsigned int A;
738 739 740
  uint8_t Q_m;
  unsigned int i,i2,q,j,j2;
  int iprime;
741
  unsigned int ret=0;
742
  //  uint8_t dummy_channel_output[(3*8*block_length)+12];
743
  int r,Kr;
744 745 746
  uint8_t *columnset;
  unsigned int sumKr=0;
  unsigned int Qprime,L,G,Q_CQI,Q_RI,H,Hprime,Hpp,Cmux,Rmux_prime,O_RCC;
747
  unsigned int Qprime_ACK,Qprime_RI,len_ACK=0,len_RI=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
748
  //  uint8_t q_ACK[MAX_ACK_PAYLOAD],q_RI[MAX_RI_PAYLOAD];
749 750 751 752 753
  int metric,metric_new;
  uint32_t x1, x2, s=0;
  int16_t ys,c;
  uint32_t wACK_idx;
  uint8_t dummy_w_cc[3*(MAX_CQI_BITS+8+32)];
754
  int16_t y[6*14*1200] __attribute__((aligned(32)));
755 756
  uint8_t ytag[14*1200];
  //  uint8_t ytag2[6*14*1200],*ytag2_ptr;
Cedric Roux's avatar
Cedric Roux committed
757
  int16_t cseq[6*14*1200] __attribute__((aligned(32)));
758
  int off;
759
  int frame = proc->frame_rx;
760
  int subframe = proc->subframe_rx;
Raymond Knopp's avatar
Raymond Knopp committed
761
  LTE_UL_eNB_HARQ_t *ulsch_harq;
762
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
nepes's avatar
nepes committed
763
  LOG_D(PHY,"ue_type %d\n",ulsch->ue_type);
laurent's avatar
laurent committed
764

765 766 767
  if (ulsch->ue_type>0)     harq_pid = 0;
  else
#endif
laurent's avatar
laurent committed
768 769 770
  {
    harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe);
  }
771 772

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,1);
773 774
  // x1 is set in lte_gold_generic
  x2 = ((uint32_t)ulsch->rnti<<14) + ((uint32_t)subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1
Raymond Knopp's avatar
Raymond Knopp committed
775
  ulsch_harq = ulsch->harq_processes[harq_pid];
776 777 778 779
  AssertFatal(harq_pid!=255,
              "FATAL ERROR: illegal harq_pid, returning\n");
  AssertFatal(ulsch_harq->Nsymb_pusch != 0,
              "FATAL ERROR: harq_pid %d, Nsymb 0!\n",harq_pid);
Raymond Knopp's avatar
Raymond Knopp committed
780 781
  nb_rb = ulsch_harq->nb_rb;
  A = ulsch_harq->TBS;
782
  Q_m = ulsch_harq->Qm;
Raymond Knopp's avatar
Raymond Knopp committed
783
  G = nb_rb * (12 * Q_m) * ulsch_harq->Nsymb_pusch;
Raymond Knopp's avatar
Raymond Knopp committed
784
  //#ifdef DEBUG_ULSCH_DECODING
785
  LOG_D(PHY,"[PUSCH %d] Frame %d, Subframe %d: ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): A %d, round %d, RV %d, O_r1 %d, O_RI %d, O_ACK %d, G %d, Q_m %d Nsymb_pusch %d nb_rb %d\n",
frtabu's avatar
frtabu committed
786 787 788 789 790 791 792 793 794 795
        harq_pid,
        proc->frame_rx,subframe,
        frame_parms->Nid_cell,ulsch->rnti,x2,
        A,
        ulsch_harq->round,
        ulsch_harq->rvidx,
        ulsch_harq->Or1,
        ulsch_harq->O_RI,
        ulsch_harq->O_ACK,
        G,
796 797 798
        ulsch_harq->Qm,
        ulsch_harq->Nsymb_pusch,
        nb_rb);
Raymond Knopp's avatar
Raymond Knopp committed
799
  //#endif
800
  //if (ulsch_harq->round == 0) { // delete for RB shortage pattern
frtabu's avatar
frtabu committed
801 802 803 804 805 806 807 808 809 810 811 812
  // This is a new packet, so compute quantities regarding segmentation
  ulsch_harq->B = A+24;
  lte_segmentation(NULL,
                   NULL,
                   ulsch_harq->B,
                   &ulsch_harq->C,
                   &ulsch_harq->Cplus,
                   &ulsch_harq->Cminus,
                   &ulsch_harq->Kplus,
                   &ulsch_harq->Kminus,
                   &ulsch_harq->F);
  //  CLEAR LLR's HERE for first packet in process
813
  //}
814
  //  printf("after segmentation c[%d] = %p\n",0,ulsch_harq->c[0]);
815
  sumKr = 0;
816 817

  for (r=0; r<ulsch_harq->C; r++) {
Raymond Knopp's avatar
Raymond Knopp committed
818 819
    if (r<ulsch_harq->Cminus)
      Kr = ulsch_harq->Kminus;
820
    else
Raymond Knopp's avatar
Raymond Knopp committed
821
      Kr = ulsch_harq->Kplus;
822

823 824
    sumKr += Kr;
  }
825

826
  AssertFatal(sumKr>0,
frtabu's avatar
frtabu committed
827 828 829 830 831 832 833 834 835
              "[eNB] ulsch_decoding.c: FATAL sumKr is 0! (Nid_cell %d, rnti %x, x2 %x): harq_pid %d round %d, RV %d, O_RI %d, O_ACK %d, G %d, subframe %d\n",
              frame_parms->Nid_cell,ulsch->rnti,x2,
              harq_pid,
              ulsch_harq->round,
              ulsch_harq->rvidx,
              ulsch_harq->O_RI,
              ulsch_harq->O_ACK,
              G,
              subframe);
836
  // Compute Q_ri
Raymond Knopp's avatar
Raymond Knopp committed
837
  Qprime = ulsch_harq->O_RI*ulsch_harq->Msc_initial*ulsch_harq->Nsymb_initial * ulsch->beta_offset_ri_times8;
838 839 840 841 842 843

  if (Qprime > 0 ) {
    if ((Qprime % (8*sumKr)) > 0)
      Qprime = 1+(Qprime/(8*sumKr));
    else
      Qprime = Qprime/(8*sumKr);
844

845 846 847 848 849 850 851
    if (Qprime > 4*nb_rb * 12)
      Qprime = 4*nb_rb * 12;
  }

  Q_RI = Q_m*Qprime;
  Qprime_RI = Qprime;
  // Compute Q_ack
Raymond Knopp's avatar
Raymond Knopp committed
852
  Qprime = ulsch_harq->O_ACK*ulsch_harq->Msc_initial*ulsch_harq->Nsymb_initial * ulsch->beta_offset_harqack_times8;
853

854 855 856 857 858 859 860 861 862 863 864 865 866
  if (Qprime > 0) {
    if ((Qprime % (8*sumKr)) > 0)
      Qprime = 1+(Qprime/(8*sumKr));
    else
      Qprime = Qprime/(8*sumKr);

    if (Qprime > (4*nb_rb * 12))
      Qprime = 4*nb_rb * 12;
  }

  //  Q_ACK = Qprime * Q_m;
  Qprime_ACK = Qprime;
#ifdef DEBUG_ULSCH_DECODING
frtabu's avatar
frtabu committed
867 868
  printf("ulsch_decoding.c: Qprime_ACK %u, Msc_initial %d, Nsymb_initial %d, sumKr %u\n",
         Qprime_ACK,ulsch_harq->Msc_initial,ulsch_harq->Nsymb_initial,sumKr);
869
#endif
870

871
  // Compute Q_cqi
Raymond Knopp's avatar
Raymond Knopp committed
872
  if (ulsch_harq->Or1 < 12)
873
    L=0;
874
  else
875
    L=8;
876

877
  // NOTE: we have to handle the case where we have a very small number of bits (condition on pg. 26 36.212)
Raymond Knopp's avatar
Raymond Knopp committed
878 879
  if (ulsch_harq->Or1 > 0)
    Qprime = (ulsch_harq->Or1 + L) * ulsch_harq->Msc_initial*ulsch_harq->Nsymb_initial * ulsch->beta_offset_cqi_times8;
880 881 882
  else
    Qprime=0;

883
  if (Qprime > 0) {  // check if ceiling is larger than floor in Q' expression
884 885 886 887 888 889
    if ((Qprime % (8*sumKr)) > 0)
      Qprime = 1+(Qprime/(8*sumKr));
    else
      Qprime = Qprime/(8*sumKr);
  }

Raymond Knopp's avatar
Raymond Knopp committed
890
  G = nb_rb * (12 * Q_m) * (ulsch_harq->Nsymb_pusch);
891
  Q_CQI = Q_m * Qprime;
Raymond Knopp's avatar
Raymond Knopp committed
892
#ifdef DEBUG_ULSCH_DECODING
893
  printf("ulsch_decoding: G %u, Q_RI %u, Q_CQI %u (L %u, Or1 %d) O_ACK %d\n",G,Q_RI,Q_CQI,L,ulsch_harq->Or1,ulsch_harq->O_ACK);
Raymond Knopp's avatar
Raymond Knopp committed
894
#endif
895
  G = G - Q_RI - Q_CQI;
896
  ulsch_harq->G = G;
897 898
  AssertFatal((int)G > 0,
              "FATAL: ulsch_decoding.c G < 0 (%d) : Q_RI %d, Q_CQI %d\n",G,Q_RI,Q_CQI);
899 900 901
  H = G + Q_CQI;
  Hprime = H/Q_m;
  // Demultiplexing/Deinterleaving of PUSCH/ACK/RI/CQI
902
  start_meas(&eNB->ulsch_demultiplexing_stats);
903
  Hpp = Hprime + Qprime_RI;
Raymond Knopp's avatar
Raymond Knopp committed
904
  Cmux       = ulsch_harq->Nsymb_pusch;
905 906 907 908
  Rmux_prime = Hpp/Cmux;
  // Clear "tag" interleaving matrix to allow for CQI/DATA identification
  memset(ytag,0,Cmux*Rmux_prime);
  i=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
909
  memset(y,LTE_NULL,Q_m*Hpp);
910 911
  // read in buffer and unscramble llrs for everything but placeholder bits
  // llrs stored per symbol correspond to columns of interleaving matrix
912
  s = lte_gold_unscram(&x1, &x2, 1);
913
  i2=0;
914 915

  for (i=0; i<((Hpp*Q_m)>>5); i++) {
916
    /*
917
    for (j=0; j<32; j++) {
918 919
      cseq[i2++] = (int16_t)((((s>>j)&1)<<1)-1);
    }
920 921 922
    */
#if defined(__x86_64__) || defined(__i386__)
#ifndef __AVX2__
frtabu's avatar
frtabu committed
923 924
    ((__m128i *)cseq)[i2++] = ((__m128i *)unscrambling_lut)[(s&65535)<<1];
    ((__m128i *)cseq)[i2++] = ((__m128i *)unscrambling_lut)[1+((s&65535)<<1)];
925
    s>>=16;
frtabu's avatar
frtabu committed
926 927
    ((__m128i *)cseq)[i2++] = ((__m128i *)unscrambling_lut)[(s&65535)<<1];
    ((__m128i *)cseq)[i2++] = ((__m128i *)unscrambling_lut)[1+((s&65535)<<1)];
928
#else
frtabu's avatar
frtabu committed
929 930
    ((__m256i *)cseq)[i2++] = ((__m256i *)unscrambling_lut)[s&65535];
    ((__m256i *)cseq)[i2++] = ((__m256i *)unscrambling_lut)[(s>>16)&65535];
931 932
#endif
#elif defined(__arm__)
frtabu's avatar
frtabu committed
933 934
    ((int16x8_t *)cseq)[i2++] = ((int16x8_t *)unscrambling_lut)[(s&65535)<<1];
    ((int16x8_t *)cseq)[i2++] = ((int16x8_t *)unscrambling_lut)[1+((s&65535)<<1)];
935
    s>>=16;
frtabu's avatar
frtabu committed
936 937
    ((int16x8_t *)cseq)[i2++] = ((int16x8_t *)unscrambling_lut)[(s&65535)<<1];
    ((int16x8_t *)cseq)[i2++] = ((int16x8_t *)unscrambling_lut)[1+((s&65535)<<1)];
938 939
#endif
    s = lte_gold_unscram(&x1, &x2, 0);
940 941
  }

942 943
  //  printf("after unscrambling c[%d] = %p\n",0,ulsch_harq->c[0]);

944 945 946 947
  if (frame_parms->Ncp == 0)
    columnset = cs_ri_normal;
  else
    columnset = cs_ri_extended;
948 949 950 951

  j=0;

  for (i=0; i<Qprime_RI; i++) {
952
    r = Rmux_prime - 1 - (i>>2);
953 954
    /*
    for (q=0;q<Q_m;q++)
955 956
      ytag2[q+(Q_m*((r*Cmux) + columnset[j]))]  = q_RI[(q+(Q_m*i))%len_RI];
    */
957
    off =((Rmux_prime*Q_m*columnset[j])+(r*Q_m));
958
    cseq[off+1] = cseq[off];  // PUSCH_y
959 960

    for (q=2; q<Q_m; q++)
961 962 963 964 965
      cseq[off+q] = -1;    // PUSCH_x

    j=(j+3)&3;
  }

966 967
  //  printf("after RI c[%d] = %p\n",0,ulsch_harq->c[0]);

968 969 970 971 972 973 974
  // HARQ-ACK Bits (Note these overwrite some bits)
  if (frame_parms->Ncp == 0)
    columnset = cs_ack_normal;
  else
    columnset = cs_ack_extended;

  j=0;
975 976

  for (i=0; i<Qprime_ACK; i++) {
977
    r = Rmux_prime - 1 - (i>>2);
978 979
    off =((Rmux_prime*Q_m*columnset[j])+(r*Q_m));

Raymond Knopp's avatar
Raymond Knopp committed
980
    if (ulsch_harq->O_ACK == 1) {
981
      if (ulsch->bundling==0)
982 983 984 985 986 987 988
        cseq[off+1] = cseq[off];  // PUSCH_y

      for (q=2; q<Q_m; q++)
        cseq[off+q] = -1;    // PUSCH_x
    } else if (ulsch_harq->O_ACK == 2) {
      for (q=2; q<Q_m; q++)
        cseq[off+q] = -1;    // PUSCH_x
989
    }
990

991
#ifdef DEBUG_ULSCH_DECODING
992
    printf("ulsch_decoding.c: ACK i %u, r %d, j %u, ColumnSet[j] %d\n",i,r,j,columnset[j]);
993 994 995 996 997
#endif
    j=(j+3)&3;
  }

  i=0;
998

999
  switch (Q_m) {
frtabu's avatar
frtabu committed
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
    case 2:
      for (j=0; j<Cmux; j++) {
        i2=j<<1;

        for (r=0; r<Rmux_prime; r++) {
          c = cseq[i];
          //  printf("ulsch %d: %d * ",i,c);
          y[i2++] = c*ulsch_llr[i++];
          //  printf("%d\n",ulsch_llr[i-1]);
          c = cseq[i];
          //  printf("ulsch %d: %d * ",i,c);
          y[i2] = c*ulsch_llr[i++];
          //  printf("%d\n",ulsch_llr[i-1]);
          i2=(i2+(Cmux<<1)-1);
        }
1015
      }
1016

frtabu's avatar
frtabu committed
1017
      break;
1018

frtabu's avatar
frtabu committed
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
    case 4:
      for (j=0; j<Cmux; j++) {
        i2=j<<2;

        for (r=0; r<Rmux_prime; r++) {
          /*
                c = cseq[i];
                y[i2++] = c*ulsch_llr[i++];
                c = cseq[i];
                y[i2++] = c*ulsch_llr[i++];
                c = cseq[i];
                y[i2++] = c*ulsch_llr[i++];
                c = cseq[i];
                y[i2] = c*ulsch_llr[i++];
                i2=(i2+(Cmux<<2)-3);
          */
          // slightly more optimized version (equivalent to above) for 16QAM to improve computational performance
          *(__m64 *)&y[i2] = _mm_sign_pi16(*(__m64 *)&ulsch_llr[i],*(__m64 *)&cseq[i]);
          i+=4;
          i2+=(Cmux<<2);
        }
1040
      }
1041

frtabu's avatar
frtabu committed
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
      break;

    case 6:
      for (j=0; j<Cmux; j++) {
        i2=j*6;

        for (r=0; r<Rmux_prime; r++) {
          c = cseq[i];
          y[i2++] = c*ulsch_llr[i++];
          c = cseq[i];
          y[i2++] = c*ulsch_llr[i++];
          c = cseq[i];
          y[i2++] = c*ulsch_llr[i++];
          c = cseq[i];
          y[i2++] = c*ulsch_llr[i++];
          c = cseq[i];
          y[i2++] = c*ulsch_llr[i++];
          c = cseq[i];
          y[i2] = c*ulsch_llr[i++];
          i2=(i2+(Cmux*6)-5);
        }
1063
      }
1064

frtabu's avatar
frtabu committed
1065
      break;
1066 1067 1068
  }

  if (i!=(H+Q_RI))
1069
    LOG_D(PHY,"ulsch_decoding.c: Error in input buffer length (j %d, H+Q_RI %d)\n",i,H+Q_RI);
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079

  // HARQ-ACK Bits (LLRs are nulled in overwritten bits after copying HARQ-ACK LLR)

  if (frame_parms->Ncp == 0)
    columnset = cs_ack_normal;
  else
    columnset = cs_ack_extended;

  j=0;

Raymond Knopp's avatar
Raymond Knopp committed
1080
  if (ulsch_harq->O_ACK == 1) {
1081
    switch (Q_m) {
frtabu's avatar
frtabu committed
1082 1083 1084
      case 2:
        len_ACK = 2;
        break;
1085

frtabu's avatar
frtabu committed
1086 1087 1088
      case 4:
        len_ACK = 4;
        break;
1089

frtabu's avatar
frtabu committed
1090 1091 1092
      case 6:
        len_ACK = 6;
        break;
1093 1094
    }
  }
1095

Raymond Knopp's avatar
Raymond Knopp committed
1096
  if (ulsch_harq->O_ACK == 2) {
1097
    switch (Q_m) {
frtabu's avatar
frtabu committed
1098 1099 1100
      case 2:
        len_ACK = 6;
        break;
1101

frtabu's avatar
frtabu committed
1102 1103 1104
      case 4:
        len_ACK = 12;
        break;
1105

frtabu's avatar
frtabu committed
1106 1107 1108
      case 6:
        len_ACK = 18;
        break;
1109 1110
    }
  }
1111

Raymond Knopp's avatar
Raymond Knopp committed
1112
  if (ulsch_harq->O_ACK > 2) {
1113
    LOG_E(PHY,"ulsch_decoding: FATAL, ACK cannot be more than 2 bits yet O_ACK:%d SFN/SF:%04d%d UE_id:%d rnti:%x\n",ulsch_harq->O_ACK,proc->frame_rx,proc->subframe_rx,UE_id,ulsch->rnti);
1114 1115 1116
    return(-1);
  }

1117
  for (i=0; i<len_ACK; i++)
Raymond Knopp's avatar
Raymond Knopp committed
1118
    ulsch_harq->q_ACK[i] = 0;
1119

1120
  for (i=0; i<Qprime_ACK; i++) {
1121
    r = Rmux_prime -1 - (i>>2);
1122 1123

    for (q=0; q<Q_m; q++) {
1124
      if (y[q+(Q_m*((r*Cmux) + columnset[j]))]!=0)
1125
        ulsch_harq->q_ACK[(q+(Q_m*i))%len_ACK] += y[q+(Q_m*((r*Cmux) + columnset[j]))];
frtabu's avatar
frtabu committed
1126

1127 1128
      y[q+(Q_m*((r*Cmux) + columnset[j]))]=0;  // NULL LLRs in ACK positions
    }
1129

1130 1131 1132
    j=(j+3)&3;
  }

1133
  //  printf("after ACKNAK c[%d] = %p\n",0,ulsch_harq->c[0]);
1134

1135
  // RI BITS
1136

Raymond Knopp's avatar
Raymond Knopp committed
1137
  if (ulsch_harq->O_RI == 1) {
1138
    switch (Q_m) {
frtabu's avatar
frtabu committed
1139 1140 1141
      case 2:
        len_RI=2;
        break;
1142

frtabu's avatar
frtabu committed
1143 1144 1145
      case 4:
        len_RI=4;
        break;
1146

frtabu's avatar
frtabu committed
1147 1148 1149
      case 6:
        len_RI=6;
        break;
1150 1151 1152
    }
  }

Raymond Knopp's avatar
Raymond Knopp committed
1153
  if (ulsch_harq->O_RI > 1) {
1154 1155 1156 1157
    LOG_E(PHY,"ulsch_decoding: FATAL, RI cannot be more than 1 bit yet\n");
    return(-1);
  }

1158
  for (i=0; i<len_RI; i++)
Raymond Knopp's avatar
Raymond Knopp committed
1159
    ulsch_harq->q_RI[i] = 0;
1160

1161 1162 1163 1164
  if (frame_parms->Ncp == 0)
    columnset = cs_ri_normal;
  else
    columnset = cs_ri_extended;
1165 1166 1167 1168

  j=0;

  for (i=0; i<Qprime_RI; i++) {
1169
    r = Rmux_prime -1 - (i>>2);
1170 1171

    for (q=0; q<Q_m; q++)
Raymond Knopp's avatar
Raymond Knopp committed
1172
      ulsch_harq->q_RI[(q+(Q_m*i))%len_RI] += y[q+(Q_m*((r*Cmux) + columnset[j]))];
1173

1174 1175 1176 1177
    ytag[(r*Cmux) + columnset[j]] = LTE_NULL;
    j=(j+3)&3;
  }

1178
  //  printf("after RI2 c[%d] = %p\n",0,ulsch_harq->c[0]);
1179
  // CQI and Data bits
1180 1181 1182
  j=0;
  j2=0;

1183
  //  r=0;
1184 1185 1186
  if (Q_RI>0) {
    for (i=0; i<(Q_CQI/Q_m); i++) {
      while (ytag[j]==LTE_NULL) {
frtabu's avatar
frtabu committed
1187 1188
        j++;
        j2+=Q_m;
1189
      }
frtabu's avatar
frtabu committed
1190

1191
      for (q=0; q<Q_m; q++) {
frtabu's avatar
frtabu committed
1192 1193 1194 1195 1196 1197 1198 1199 1200
        //      ys = y[q+(Q_m*((r*Cmux)+j))];
        ys = y[q+j2];

        if (ys>127)
          ulsch_harq->q[q+(Q_m*i)] = 127;
        else if (ys<-128)
          ulsch_harq->q[q+(Q_m*i)] = -128;
        else
          ulsch_harq->q[q+(Q_m*i)] = ys;
1201
      }
frtabu's avatar
frtabu committed
1202

1203 1204
      j2+=Q_m;
    }
frtabu's avatar
frtabu committed
1205

1206
    switch (Q_m) {
frtabu's avatar
frtabu committed
1207 1208 1209 1210 1211 1212
      case 2:
        for (iprime=0; iprime<G;) {
          while (ytag[j]==LTE_NULL) {
            j++;
            j2+=2;
          }
1213

frtabu's avatar
frtabu committed
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
          ulsch_harq->e[iprime++] = y[j2++];
          ulsch_harq->e[iprime++] = y[j2++];
        }

        break;

      case 4:
        for (iprime=0; iprime<G;) {
          while (ytag[j]==LTE_NULL) {
            j++;
            j2+=4;
          }

          ulsch_harq->e[iprime++] = y[j2++];
          ulsch_harq->e[iprime++] = y[j2++];
          ulsch_harq->e[iprime++] = y[j2++];
          ulsch_harq->e[iprime++] = y[j2++];
        }
1232

frtabu's avatar
frtabu committed
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
        break;

      case 6:
        for (iprime=0; iprime<G;) {
          while (ytag[j]==LTE_NULL) {
            j++;
            j2+=6;
          }

          ulsch_harq->e[iprime++] = y[j2++];
          ulsch_harq->e[iprime++] = y[j2++];
          ulsch_harq->e[iprime++] = y[j2++];
          ulsch_harq->e[iprime++] = y[j2++];
          ulsch_harq->e[iprime++] = y[j2++];
          ulsch_harq->e[iprime++] = y[j2++];
        }

        break;
    }
1252
  } // Q_RI>0
1253 1254 1255
  else {
    for (i=0; i<(Q_CQI/Q_m); i++) {
      for (q=0; q<Q_m; q++) {
frtabu's avatar
frtabu committed
1256 1257 1258 1259 1260 1261 1262 1263
        ys = y[q+j2];

        if (ys>127)
          ulsch_harq->q[q+(Q_m*i)] = 127;
        else if (ys<-128)
          ulsch_harq->q[q+(Q_m*i)] = -128;
        else
          ulsch_harq->q[q+(Q_m*i)] = ys;
1264
      }
frtabu's avatar
frtabu committed
1265

1266
      j2+=Q_m;
1267
    }
frtabu's avatar
frtabu committed
1268

1269
    /* To be improved according to alignment of j2
frtabu's avatar
frtabu committed
1270 1271
    #if defined(__x86_64__)||defined(__i386__)
    #ifndef __AVX2__
1272 1273
    for (iprime=0; iprime<G;iprime+=8,j2+=8)
      *((__m128i *)&ulsch_harq->e[iprime]) = *((__m128i *)&y[j2]);
frtabu's avatar
frtabu committed
1274
    #else
1275 1276
    for (iprime=0; iprime<G;iprime+=16,j2+=16)
      *((__m256i *)&ulsch_harq->e[iprime]) = *((__m256i *)&y[j2]);
frtabu's avatar
frtabu committed
1277 1278
    #endif
    #elif defined(__arm__)
1279 1280
    for (iprime=0; iprime<G;iprime+=8,j2+=8)
      *((int16x8_t *)&ulsch_harq->e[iprime]) = *((int16x8_t *)&y[j2]);
frtabu's avatar
frtabu committed
1281
    #endif
1282 1283
    */
    int16_t *yp,*ep;
frtabu's avatar
frtabu committed
1284 1285 1286 1287

    for (iprime=0,yp=&y[j2],ep=&ulsch_harq->e[0];
         iprime<G;
         iprime+=8,j2+=8,ep+=8,yp+=8) {
1288 1289 1290 1291 1292 1293 1294 1295 1296
      ep[0] = yp[0];
      ep[1] = yp[1];
      ep[2] = yp[2];
      ep[3] = yp[3];
      ep[4] = yp[4];
      ep[5] = yp[5];
      ep[6] = yp[6];
      ep[7] = yp[7];
    }
1297
  }
1298

frtabu's avatar
frtabu committed
1299
  stop_meas(&eNB->ulsch_demultiplexing_stats);
1300
  //  printf("after ACKNAK2 c[%d] = %p (iprime %d, G %d)\n",0,ulsch_harq->c[0],iprime,G);
1301
  // Do CQI/RI/HARQ-ACK Decoding first and pass to MAC
1302
  // HARQ-ACK
1303
  wACK_idx = (ulsch->bundling==0) ? 4 : ((Nbundled-1)&3);
1304

Raymond Knopp's avatar
Raymond Knopp committed
1305
  if (ulsch_harq->O_ACK == 1) {
1306 1307 1308 1309 1310 1311 1312
    ulsch_harq->q_ACK[0] *= wACK_RX[wACK_idx][0];
    ulsch_harq->q_ACK[0] += (ulsch->bundling==0) ? ulsch_harq->q_ACK[1]*wACK_RX[wACK_idx][0] : ulsch_harq->q_ACK[1]*wACK_RX[wACK_idx][1];

    if (ulsch_harq->q_ACK[0] < 0)
      ulsch_harq->o_ACK[0] = 0;
    else
      ulsch_harq->o_ACK[0] = 1;
1313
  }
1314

Raymond Knopp's avatar
Raymond Knopp committed
1315
  if (ulsch_harq->O_ACK == 2) {
1316
    switch (Q_m) {
frtabu's avatar
frtabu committed
1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
      case 2:
        ulsch_harq->q_ACK[0] = ulsch_harq->q_ACK[0]*wACK_RX[wACK_idx][0] + ulsch_harq->q_ACK[3]*wACK_RX[wACK_idx][1];
        ulsch_harq->q_ACK[1] = ulsch_harq->q_ACK[1]*wACK_RX[wACK_idx][0] + ulsch_harq->q_ACK[4]*wACK_RX[wACK_idx][1];
        ulsch_harq->q_ACK[2] = ulsch_harq->q_ACK[2]*wACK_RX[wACK_idx][0] + ulsch_harq->q_ACK[5]*wACK_RX[wACK_idx][1];
        break;

      case 4:
        ulsch_harq->q_ACK[0] = ulsch_harq->q_ACK[0]*wACK_RX[wACK_idx][0] + ulsch_harq->q_ACK[5]*wACK_RX[wACK_idx][1];
        ulsch_harq->q_ACK[1] = ulsch_harq->q_ACK[1]*wACK_RX[wACK_idx][0] + ulsch_harq->q_ACK[8]*wACK_RX[wACK_idx][1];
        ulsch_harq->q_ACK[2] = ulsch_harq->q_ACK[4]*wACK_RX[wACK_idx][0] + ulsch_harq->q_ACK[9]*wACK_RX[wACK_idx][1];
        break;

      case 6:
        ulsch_harq->q_ACK[0] =  ulsch_harq->q_ACK[0]*wACK_RX[wACK_idx][0] + ulsch_harq->q_ACK[7]*wACK_RX[wACK_idx][1];
        ulsch_harq->q_ACK[1] =  ulsch_harq->q_ACK[1]*wACK_RX[wACK_idx][0] + ulsch_harq->q_ACK[12]*wACK_RX[wACK_idx][1];
        ulsch_harq->q_ACK[2] =  ulsch_harq->q_ACK[6]*wACK_RX[wACK_idx][0] + ulsch_harq->q_ACK[13]*wACK_RX[wACK_idx][1];
        break;
1334
    }
1335

Raymond Knopp's avatar
Raymond Knopp committed
1336 1337 1338 1339
    ulsch_harq->o_ACK[0] = 1;
    ulsch_harq->o_ACK[1] = 1;
    metric     = ulsch_harq->q_ACK[0]+ulsch_harq->q_ACK[1]-ulsch_harq->q_ACK[2];
    metric_new = -ulsch_harq->q_ACK[0]+ulsch_harq->q_ACK[1]+ulsch_harq->q_ACK[2];
1340 1341

    if (metric_new > metric) {
Raymond Knopp's avatar
Raymond Knopp committed
1342 1343
      ulsch_harq->o_ACK[0]=0;
      ulsch_harq->o_ACK[1]=1;
1344 1345
      metric = metric_new;
    }
1346

Raymond Knopp's avatar
Raymond Knopp committed
1347
    metric_new = ulsch_harq->q_ACK[0]-ulsch_harq->q_ACK[1]+ulsch_harq->q_ACK[2];
1348 1349

    if (metric_new > metric) {
Raymond Knopp's avatar
Raymond Knopp committed
1350 1351
      ulsch_harq->o_ACK[0] = 1;
      ulsch_harq->o_ACK[1] = 0;
1352 1353
      metric = metric_new;
    }
1354

Raymond Knopp's avatar
Raymond Knopp committed
1355
    metric_new = -ulsch_harq->q_ACK[0]-ulsch_harq->q_ACK[1]-ulsch_harq->q_ACK[2];
1356 1357

    if (metric_new > metric) {
Raymond Knopp's avatar
Raymond Knopp committed
1358 1359
      ulsch_harq->o_ACK[0] = 0;
      ulsch_harq->o_ACK[1] = 0;
1360 1361 1362 1363 1364 1365
      metric = metric_new;
    }
  }

  // RI

1366
  // rank 1
Raymond Knopp's avatar
Raymond Knopp committed
1367
  if ((ulsch_harq->O_RI == 1) && (Qprime_RI > 0)) {
1368
    ulsch_harq->o_RI[0] = ((ulsch_harq->q_RI[0] + ulsch_harq->q_RI[Q_m/2]) > 0) ? 0 : 1;
1369
  }
1370

1371
  // CQI
1372
  //  printf("before cqi c[%d] = %p\n",0,ulsch_harq->c[0]);
1373
  ulsch_harq->cqi_crc_status = 0;
frtabu's avatar
frtabu committed
1374

1375
  if (Q_CQI>0) {
Raymond Knopp's avatar
Raymond Knopp committed
1376 1377
    memset((void *)&dummy_w_cc[0],0,3*(ulsch_harq->Or1+8+32));
    O_RCC = generate_dummy_w_cc(ulsch_harq->Or1+8,
1378
                                &dummy_w_cc[0]);
1379
    lte_rate_matching_cc_rx(O_RCC,
1380 1381 1382 1383
                            Q_CQI,
                            ulsch_harq->o_w,
                            dummy_w_cc,
                            ulsch_harq->q);
Raymond Knopp's avatar
Raymond Knopp committed
1384
    sub_block_deinterleaving_cc((unsigned int)(ulsch_harq->Or1+8),
1385 1386
                                &ulsch_harq->o_d[96],
                                &ulsch_harq->o_w[0]);
Cedric Roux's avatar
Cedric Roux committed
1387 1388
    memset(ulsch_harq->o,0,(7+8+ulsch_harq->Or1) / 8);
    phy_viterbi_lte_sse2(ulsch_harq->o_d+96,ulsch_harq->o,8+ulsch_harq->Or1);
1389

Cedric Roux's avatar
Cedric Roux committed
1390
    if (extract_cqi_crc(ulsch_harq->o,ulsch_harq->Or1) == (crc8(ulsch_harq->o,ulsch_harq->Or1)>>24))
Raymond Knopp's avatar
Raymond Knopp committed
1391
      ulsch_harq->cqi_crc_status = 1;
1392 1393

#ifdef DEBUG_ULSCH_DECODING
Raymond Knopp's avatar
Raymond Knopp committed
1394
    printf("ulsch_decoding: Or1=%d\n",ulsch_harq->Or1);
1395 1396

    for (i=0; i<1+((8+ulsch_harq->Or1)/8); i++)
1397
      printf("ulsch_decoding: O[%u] %d\n",i,ulsch_harq->o[i]);
1398

Raymond Knopp's avatar
Raymond Knopp committed
1399
    if (ulsch_harq->cqi_crc_status == 1)
Cedric Roux's avatar
Cedric Roux committed
1400
      printf("RX CQI CRC OK (%x)\n",extract_cqi_crc(ulsch_harq->o,ulsch_harq->Or1));
1401
    else
Cedric Roux's avatar
Cedric Roux committed
1402
      printf("RX CQI CRC NOT OK (%x)\n",extract_cqi_crc(ulsch_harq->o,ulsch_harq->Or1));
1403

1404 1405 1406
#endif
  }

Cedric Roux's avatar
Cedric Roux committed
1407
  LOG_D(PHY,"frame %d subframe %d O_ACK:%d o_ACK[]=%d:%d:%d:%d\n",frame,subframe,ulsch_harq->O_ACK,ulsch_harq->o_ACK[0],ulsch_harq->o_ACK[1],ulsch_harq->o_ACK[2],ulsch_harq->o_ACK[3]);
1408
  // Do ULSCH Decoding for data portion
laurent's avatar
laurent committed
1409
  ret = ulsch_decoding_data_all(eNB,UE_id,harq_pid,llr8_flag);
1410
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,0);
1411 1412
  return(ret);
}