ulsch_decoding.c 42.5 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
#include <executables/split_headers.h>
48

49
extern WORKER_CONF_t get_thread_worker_conf(void);
50

51

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

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

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

        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;
76 77
      }
    }
78 79

    free16(ulsch,sizeof(LTE_eNB_ULSCH_t));
80 81 82
  }
}

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

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

frtabu's avatar
frtabu committed
93 94 95
    case 25:
      bw_scaling =4;
      break;
96

frtabu's avatar
frtabu committed
97 98 99
    case 50:
      bw_scaling =2;
      break;
100

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

106
  ulsch = (LTE_eNB_ULSCH_t *)malloc16(sizeof(LTE_eNB_ULSCH_t));
107

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

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

117
      if (ulsch->harq_processes[i]) {
118
        memset(ulsch->harq_processes[i],0,sizeof(LTE_UL_eNB_HARQ_t));
119
        ulsch->harq_processes[i]->bb = (uint8_t *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling);
120

121 122
        if (ulsch->harq_processes[i]->bb)
          memset(ulsch->harq_processes[i]->bb,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling);
123 124 125 126 127
        else
          exit_flag=3;

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

130 131 132 133 134
            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
135
            ulsch->harq_processes[i]->d[r] = (short *)malloc16(((3*8*6144)+12+96)*sizeof(short));
136 137 138 139 140 141 142 143 144

            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;
145 146 147 148 149 150
      }
    }

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

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

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

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

165
    for (i=0; i<8; i++) {
166
      if (ulsch->harq_processes[i]) {
167 168 169 170 171
        //    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;
172 173 174 175 176 177
        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
178

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

183 184 185 186 187
        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;
188 189
      }
    }
frtabu's avatar
frtabu committed
190

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


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



216

frtabu's avatar
frtabu committed
217
int ulsch_decoding_data_2thread0(td_params *tdp) {
218 219 220 221
  PHY_VARS_eNB *eNB = tdp->eNB;
  int UE_id         = tdp->UE_id;
  int harq_pid      = tdp->harq_pid;
  int llr8_flag     = tdp->llr8_flag;
222
  unsigned int r,r_offset=0,Kr,Kr_bytes;
223 224 225 226 227 228
  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];
229
  int Q_m = ulsch_harq->Qm;
230
  int G = ulsch_harq->G;
Raymond Knopp's avatar
Raymond Knopp committed
231
  uint32_t E=0;
232 233
  uint32_t Gp,GpmodC,Nl=1;
  uint32_t C = ulsch_harq->C;
234
  decoder_if_t *tc;
235 236

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

  // 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
253

254 255 256 257
    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
258

259
    r_offset += E;
260 261 262 263 264 265

    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));
    }
266 267 268
  }

  // go through second half of segments
269
  for (; r<(ulsch_harq->C); r++) {
270 271 272 273 274 275 276 277 278
    //    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));
279
    ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8),
frtabu's avatar
frtabu committed
280
                                          (uint8_t *)&dummy_w[r][0],
281 282
                                          (r==0) ? ulsch_harq->F : 0);
#ifdef DEBUG_ULSCH_DECODING
frtabu's avatar
frtabu committed
283 284 285 286 287 288
    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);
289 290
#endif

291
    if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r],
292 293
                                   G,
                                   ulsch_harq->w[r],
frtabu's avatar
frtabu committed
294
                                   (uint8_t *) &dummy_w[r][0],
295
                                   ulsch_harq->eE+r_offset,
296 297 298 299 300 301
                                   ulsch_harq->C,
                                   NSOFT,
                                   0,   //Uplink
                                   1,
                                   ulsch_harq->rvidx,
                                   (ulsch_harq->round==0)?1:0,  // clear
302
                                   ulsch_harq->Qm,
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
                                   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
319

320
    ret = tc(&ulsch_harq->d[r][96],
321
             NULL,
frtabu's avatar
frtabu committed
322
             ulsch_harq->c[r],
323
             NULL,
frtabu's avatar
frtabu committed
324 325 326 327 328 329 330 331 332 333 334 335
             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);

336
    // Reassembly of Transport block here
337 338 339

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

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

  return(ret);
}

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

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

Wang Tsu-Han's avatar
Wang Tsu-Han committed
371
    if(oai_exit) break;
372

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

    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) {
388
  L1_proc_t *proc = &eNB->proc;
389
  unsigned int r,r_offset=0,Kr,Kr_bytes;
390 391 392 393 394 395
  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];
396
  int G = ulsch_harq->G;
397
  unsigned int E;
398
  int Cby2;
399
  decoder_if_t *tc;
400 401 402 403 404
  struct timespec wait;
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;

  if (llr8_flag == 0)
405
    tc = decoder16;
406
  else
407
    tc = decoder8;
408

409 410 411 412 413 414
  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
415

416 417 418 419 420 421
    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
422

423 424 425 426 427
    ++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
428 429

    // wakeup worker to do second half segments
430 431 432 433 434
    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);
    }
435 436

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

  // go through first half of segments in main thread
443
  for (r=0; r<Cby2; r++) {
444 445 446 447 448 449 450 451 452
    //    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));
453
    ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8),
frtabu's avatar
frtabu committed
454
                                          (uint8_t *)&dummy_w[r][0],
455 456
                                          (r==0) ? ulsch_harq->F : 0);
#ifdef DEBUG_ULSCH_DECODING
frtabu's avatar
frtabu committed
457 458 459 460 461 462
    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);
463 464 465
#endif
    start_meas(&eNB->ulsch_rate_unmatching_stats);

466
    if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r],
467 468
                                   G,
                                   ulsch_harq->w[r],
frtabu's avatar
frtabu committed
469
                                   (uint8_t *) &dummy_w[r][0],
470
                                   ulsch_harq->eE+r_offset,
471 472 473 474 475 476
                                   ulsch_harq->C,
                                   NSOFT,
                                   0,   //Uplink
                                   1,
                                   ulsch_harq->rvidx,
                                   (ulsch_harq->round==0)?1:0,  // clear
477
                                   ulsch_harq->Qm,
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
                                   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],
500
             NULL,
frtabu's avatar
frtabu committed
501
             ulsch_harq->c[r],
502
             NULL,
frtabu's avatar
frtabu committed
503 504 505 506 507 508 509 510 511 512 513 514 515
             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
516 517 518

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

523
      Kr_bytes = Kr>>3;
frtabu's avatar
frtabu committed
524

525
      if (r==0) {
526
        memcpy(ulsch_harq->bb,
frtabu's avatar
frtabu committed
527 528 529
               &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);
530
      } else {
531
        memcpy(ulsch_harq->bb+offset,
frtabu's avatar
frtabu committed
532 533 534
               ulsch_harq->c[r],
               Kr_bytes - ((ulsch_harq->C>1)?3:0));
        offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0));
535 536 537 538 539
      }
    } else {
      break;
    }

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

frtabu's avatar
frtabu committed
544 545
  // wait for worker to finish
  wait_on_busy_condition(&proc->mutex_td,&proc->cond_td,&proc->instance_cnt_td,"td thread");
546 547 548 549
  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) {
550
  unsigned int r,r_offset=0,Kr,Kr_bytes;
551 552 553 554 555 556
  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];
557
  int G = ulsch_harq->G;
558
  unsigned int EE;
559
  decoder_if_t *tc;
560 561

  if (llr8_flag == 0)
562
    tc = *decoder16;
563
  else
564
    tc = *decoder8;
565 566 567 568 569 570 571 572 573 574 575

  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));
576
    ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8),
frtabu's avatar
frtabu committed
577
                                          (uint8_t *)&dummy_w[r][0],
578 579
                                          (r==0) ? ulsch_harq->F : 0);
#ifdef DEBUG_ULSCH_DECODING
frtabu's avatar
frtabu committed
580 581 582 583 584 585
    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);
586 587
#endif
    start_meas(&eNB->ulsch_rate_unmatching_stats);
Raymond Knopp's avatar
Raymond Knopp committed
588

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

608
    stop_meas(&eNB->ulsch_rate_unmatching_stats);
609
    r_offset += EE;
610 611 612 613 614
    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
615

616 617 618 619
    if (ulsch_harq->C == 1)
      crc_type = CRC24_A;
    else
      crc_type = CRC24_B;
620
#ifdef FS6
621 622 623
    if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) {
      // r is the segment id,
      // Kr is the segment length in short 
624
      // *3 because LTE redudancy scheme
625
      sendFs6Ul(eNB, UE_id, harq_pid, r, &ulsch_harq->d[r][96], Kr*sizeof(int16_t)*3);
626
      int iter=tc(&ulsch_harq->d[r][96],
627 628 629 630 631 632 633 634 635 636 637 638 639
             NULL,
             ulsch_harq->c[r],
             NULL,
             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,
640 641 642 643 644 645 646
             &eNB->ulsch_tc_intl2_stats);
      LOG_D(PHY, "Cu should decode in %d iter\n",iter);
      if ( iter == 5 ) { 
	      for (int i=0; i < Kr; i++ )
		      printf("%hx:", ulsch_harq->d[r][96+i]);
	      printf("\n");
      }
647

648 649
      return 0;
    }
650 651

    #endif
652
    start_meas(&eNB->ulsch_turbo_decoding_stats);
Raymond Knopp's avatar
Raymond Knopp committed
653
    ret = tc(&ulsch_harq->d[r][96],
654
             NULL,
frtabu's avatar
frtabu committed
655
             ulsch_harq->c[r],
656
             NULL,
frtabu's avatar
frtabu committed
657 658 659 660 661 662 663 664 665 666 667
             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
668
    stop_meas(&eNB->ulsch_turbo_decoding_stats);
669
    LOG_D(PHY,"turbo decode in %d iter\n",ret);
frtabu's avatar
frtabu committed
670 671

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

673 674
    if (ret != (1+ulsch->max_turbo_iterations)) {
      if (r<ulsch_harq->Cminus)
frtabu's avatar
frtabu committed
675
        Kr = ulsch_harq->Kminus;
676
      else
frtabu's avatar
frtabu committed
677 678
        Kr = ulsch_harq->Kplus;

679
      Kr_bytes = Kr>>3;
frtabu's avatar
frtabu committed
680

681
      if (r==0) {
682
        memcpy(ulsch_harq->bb,
frtabu's avatar
frtabu committed
683 684 685
               &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);
686
      } else {
687
        memcpy(ulsch_harq->bb+offset,
frtabu's avatar
frtabu committed
688 689 690
               ulsch_harq->c[r],
               Kr_bytes - ((ulsch_harq->C>1)?3:0));
        offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0));
691 692 693
      }
    } else {
      break;
Raymond Knopp's avatar
Raymond Knopp committed
694 695 696
    }
  }

697 698 699
  return(ret);
}

frtabu's avatar
frtabu committed
700
int ulsch_decoding_data_all(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) {
701
  int ret = 0;
702
  /*if(get_thread_worker_conf() == WORKER_ENABLE)
703 704 705
  {
    ret = ulsch_decoding_data_2thread(eNB,UE_id,harq_pid,llr8_flag);
  }
706
  else*/
707 708 709 710 711 712
  {
    ret = ulsch_decoding_data(eNB,UE_id,harq_pid,llr8_flag);
  }
  return ret;
}

713
static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, unsigned char reset) __attribute__((always_inline));
frtabu's avatar
frtabu committed
714
static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, unsigned char reset) {
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
  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);
    }
  }
730

731 732 733 734 735 736
  *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
737
}
frtabu's avatar
frtabu committed
738

739
unsigned int  ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,
740 741 742
                             uint8_t UE_id,
                             uint8_t control_only_flag,
                             uint8_t Nbundled,
frtabu's avatar
frtabu committed
743
                             uint8_t llr8_flag) {
744 745 746
  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];
747 748
  uint8_t harq_pid;
  unsigned short nb_rb;
749
  unsigned int A;
750 751 752
  uint8_t Q_m;
  unsigned int i,i2,q,j,j2;
  int iprime;
753
  unsigned int ret=0;
754
  //  uint8_t dummy_channel_output[(3*8*block_length)+12];
755
  int r,Kr;
756 757 758
  uint8_t *columnset;
  unsigned int sumKr=0;
  unsigned int Qprime,L,G,Q_CQI,Q_RI,H,Hprime,Hpp,Cmux,Rmux_prime,O_RCC;
759
  unsigned int Qprime_ACK,Qprime_RI,len_ACK=0,len_RI=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
760
  //  uint8_t q_ACK[MAX_ACK_PAYLOAD],q_RI[MAX_RI_PAYLOAD];
761 762 763 764 765
  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)];
766
  int16_t y[6*14*1200] __attribute__((aligned(32)));
767 768
  uint8_t ytag[14*1200];
  //  uint8_t ytag2[6*14*1200],*ytag2_ptr;
Cedric Roux's avatar
Cedric Roux committed
769
  int16_t cseq[6*14*1200] __attribute__((aligned(32)));
770
  int off;
771
  int frame = proc->frame_rx;
772
  int subframe = proc->subframe_rx;
Raymond Knopp's avatar
Raymond Knopp committed
773
  LTE_UL_eNB_HARQ_t *ulsch_harq;
774

775
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
nepes's avatar
nepes committed
776
  LOG_D(PHY,"ue_type %d\n",ulsch->ue_type);
777 778 779 780 781 782
  if (ulsch->ue_type>0)     harq_pid = 0;
  else
#endif
    {
      harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe);
    }
783 784

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,1);
785 786 787

  // 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
788
  ulsch_harq = ulsch->harq_processes[harq_pid];
789 790 791 792
  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
793 794
  nb_rb = ulsch_harq->nb_rb;
  A = ulsch_harq->TBS;
795
  Q_m = ulsch_harq->Qm;
Raymond Knopp's avatar
Raymond Knopp committed
796
  G = nb_rb * (12 * Q_m) * ulsch_harq->Nsymb_pusch;
Raymond Knopp's avatar
Raymond Knopp committed
797
  //#ifdef DEBUG_ULSCH_DECODING
798
  LOG_D(PHY,"[PUSCH harq %d] Frame %d, Subframe %d: ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): TBS %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
799 800 801 802 803 804 805 806 807 808
        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,
809 810 811
        ulsch_harq->Qm,
        ulsch_harq->Nsymb_pusch,
        nb_rb);
Raymond Knopp's avatar
Raymond Knopp committed
812
  //#endif
813
  //if (ulsch_harq->round == 0) { // delete for RB shortage pattern
frtabu's avatar
frtabu committed
814 815 816 817 818 819 820 821 822 823 824 825
  // 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
826
  //}
827
  //  printf("after segmentation c[%d] = %p\n",0,ulsch_harq->c[0]);
828
  sumKr = 0;
829 830

  for (r=0; r<ulsch_harq->C; r++) {
Raymond Knopp's avatar
Raymond Knopp committed
831 832
    if (r<ulsch_harq->Cminus)
      Kr = ulsch_harq->Kminus;
833
    else
Raymond Knopp's avatar
Raymond Knopp committed
834
      Kr = ulsch_harq->Kplus;
835

836 837
    sumKr += Kr;
  }
838

839
  AssertFatal(sumKr>0,
frtabu's avatar
frtabu committed
840 841 842 843 844 845 846 847 848
              "[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);
849
  // Compute Q_ri
Raymond Knopp's avatar
Raymond Knopp committed
850
  Qprime = ulsch_harq->O_RI*ulsch_harq->Msc_initial*ulsch_harq->Nsymb_initial * ulsch->beta_offset_ri_times8;
851 852 853 854 855 856

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

858 859 860 861 862 863 864
    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
865
  Qprime = ulsch_harq->O_ACK*ulsch_harq->Msc_initial*ulsch_harq->Nsymb_initial * ulsch->beta_offset_harqack_times8;
866

867 868 869 870 871 872 873 874 875 876 877 878 879
  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
880 881
  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);
882
#endif
883

884
  // Compute Q_cqi
Raymond Knopp's avatar
Raymond Knopp committed
885
  if (ulsch_harq->Or1 < 12)
886
    L=0;
887
  else
888
    L=8;
889

890
  // 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
891 892
  if (ulsch_harq->Or1 > 0)
    Qprime = (ulsch_harq->Or1 + L) * ulsch_harq->Msc_initial*ulsch_harq->Nsymb_initial * ulsch->beta_offset_cqi_times8;
893 894 895
  else
    Qprime=0;

896
  if (Qprime > 0) {  // check if ceiling is larger than floor in Q' expression
897 898 899 900 901 902
    if ((Qprime % (8*sumKr)) > 0)
      Qprime = 1+(Qprime/(8*sumKr));
    else
      Qprime = Qprime/(8*sumKr);
  }

Raymond Knopp's avatar
Raymond Knopp committed
903
  G = nb_rb * (12 * Q_m) * (ulsch_harq->Nsymb_pusch);
904
  Q_CQI = Q_m * Qprime;
Raymond Knopp's avatar
Raymond Knopp committed
905
#ifdef DEBUG_ULSCH_DECODING
906
  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
907
#endif
908
  G = G - Q_RI - Q_CQI;
909
  ulsch_harq->G = G;
910 911
  AssertFatal((int)G > 0,
              "FATAL: ulsch_decoding.c G < 0 (%d) : Q_RI %d, Q_CQI %d\n",G,Q_RI,Q_CQI);
912 913 914
  H = G + Q_CQI;
  Hprime = H/Q_m;
  // Demultiplexing/Deinterleaving of PUSCH/ACK/RI/CQI
915
  start_meas(&eNB->ulsch_demultiplexing_stats);
916
  Hpp = Hprime + Qprime_RI;
Raymond Knopp's avatar
Raymond Knopp committed
917
  Cmux       = ulsch_harq->Nsymb_pusch;
918 919 920 921
  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
922
  memset(y,LTE_NULL,Q_m*Hpp);
923 924
  // read in buffer and unscramble llrs for everything but placeholder bits
  // llrs stored per symbol correspond to columns of interleaving matrix
925
  s = lte_gold_unscram(&x1, &x2, 1);
926
  i2=0;
927 928

  for (i=0; i<((Hpp*Q_m)>>5); i++) {
929
    /*
930
    for (j=0; j<32; j++) {
931 932
      cseq[i2++] = (int16_t)((((s>>j)&1)<<1)-1);
    }
933 934 935
    */
#if defined(__x86_64__) || defined(__i386__)
#ifndef __AVX2__
frtabu's avatar
frtabu committed
936 937
    ((__m128i *)cseq)[i2++] = ((__m128i *)unscrambling_lut)[(s&65535)<<1];
    ((__m128i *)cseq)[i2++] = ((__m128i *)unscrambling_lut)[1+((s&65535)<<1)];
938
    s>>=16;
frtabu's avatar
frtabu committed
939 940
    ((__m128i *)cseq)[i2++] = ((__m128i *)unscrambling_lut)[(s&65535)<<1];
    ((__m128i *)cseq)[i2++] = ((__m128i *)unscrambling_lut)[1+((s&65535)<<1)];
941
#else
frtabu's avatar
frtabu committed
942 943
    ((__m256i *)cseq)[i2++] = ((__m256i *)unscrambling_lut)[s&65535];
    ((__m256i *)cseq)[i2++] = ((__m256i *)unscrambling_lut)[(s>>16)&65535];
944 945
#endif
#elif defined(__arm__)
frtabu's avatar
frtabu committed
946 947
    ((int16x8_t *)cseq)[i2++] = ((int16x8_t *)unscrambling_lut)[(s&65535)<<1];
    ((int16x8_t *)cseq)[i2++] = ((int16x8_t *)unscrambling_lut)[1+((s&65535)<<1)];
948
    s>>=16;
frtabu's avatar
frtabu committed
949 950
    ((int16x8_t *)cseq)[i2++] = ((int16x8_t *)unscrambling_lut)[(s&65535)<<1];
    ((int16x8_t *)cseq)[i2++] = ((int16x8_t *)unscrambling_lut)[1+((s&65535)<<1)];
951 952
#endif
    s = lte_gold_unscram(&x1, &x2, 0);
953 954
  }

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

957 958 959 960
  if (frame_parms->Ncp == 0)
    columnset = cs_ri_normal;
  else
    columnset = cs_ri_extended;
961 962 963 964

  j=0;

  for (i=0; i<Qprime_RI; i++) {
965
    r = Rmux_prime - 1 - (i>>2);
966 967
    /*
    for (q=0;q<Q_m;q++)
968 969
      ytag2[q+(Q_m*((r*Cmux) + columnset[j]))]  = q_RI[(q+(Q_m*i))%len_RI];
    */
970
    off =((Rmux_prime*Q_m*columnset[j])+(r*Q_m));
971
    cseq[off+1] = cseq[off];  // PUSCH_y
972 973

    for (q=2; q<Q_m; q++)
974 975 976 977 978
      cseq[off+q] = -1;    // PUSCH_x

    j=(j+3)&3;
  }

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

981 982 983 984 985 986 987
  // HARQ-ACK Bits (Note these overwrite some bits)
  if (frame_parms->Ncp == 0)
    columnset = cs_ack_normal;
  else
    columnset = cs_ack_extended;

  j=0;
988 989

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

Raymond Knopp's avatar
Raymond Knopp committed
993
    if (ulsch_harq->O_ACK == 1) {
994
      if (ulsch->bundling==0)
995 996 997 998 999 1000 1001
        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
1002
    }
1003

1004
#ifdef DEBUG_ULSCH_DECODING
1005
    printf("ulsch_decoding.c: ACK i %u, r %d, j %u, ColumnSet[j] %d\n",i,r,j,columnset[j]);
1006 1007 1008 1009 1010
#endif
    j=(j+3)&3;
  }

  i=0;
1011

1012
  switch (Q_m) {
frtabu's avatar
frtabu committed
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
    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);
        }
1028
      }
1029

frtabu's avatar
frtabu committed
1030
      break;
1031

frtabu's avatar
frtabu committed
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
    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);
        }
1053
      }
1054

frtabu's avatar
frtabu committed
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
      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);
        }
1076
      }
1077

frtabu's avatar
frtabu committed
1078
      break;
1079 1080 1081
  }

  if (i!=(H+Q_RI))
1082
    LOG_D(PHY,"ulsch_decoding.c: Error in input buffer length (j %d, H+Q_RI %d)\n",i,H+Q_RI);
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092

  // 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
1093
  if (ulsch_harq->O_ACK == 1) {
1094
    switch (Q_m) {
frtabu's avatar
frtabu committed
1095 1096 1097
      case 2:
        len_ACK = 2;
        break;
1098

frtabu's avatar
frtabu committed
1099 1100 1101
      case 4:
        len_ACK = 4;
        break;
1102

frtabu's avatar
frtabu committed
1103 1104 1105
      case 6:
        len_ACK = 6;
        break;
1106 1107
    }
  }
1108

Raymond Knopp's avatar
Raymond Knopp committed
1109
  if (ulsch_harq->O_ACK == 2) {
1110
    switch (Q_m) {
frtabu's avatar
frtabu committed
1111 1112 1113
      case 2:
        len_ACK = 6;
        break;
1114

frtabu's avatar
frtabu committed
1115 1116 1117
      case 4:
        len_ACK = 12;
        break;
1118

frtabu's avatar
frtabu committed
1119 1120 1121
      case 6:
        len_ACK = 18;
        break;
1122 1123
    }
  }
1124

Raymond Knopp's avatar
Raymond Knopp committed
1125
  if (ulsch_harq->O_ACK > 2) {
1126
    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);
1127 1128 1129
    return(-1);
  }

1130
  for (i=0; i<len_ACK; i++)
Raymond Knopp's avatar
Raymond Knopp committed
1131
    ulsch_harq->q_ACK[i] = 0;
1132

1133
  for (i=0; i<Qprime_ACK; i++) {
1134
    r = Rmux_prime -1 - (i>>2);
1135 1136

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

1140 1141
      y[q+(Q_m*((r*Cmux) + columnset[j]))]=0;  // NULL LLRs in ACK positions
    }
1142

1143 1144 1145
    j=(j+3)&3;
  }

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

1148
  // RI BITS
1149

Raymond Knopp's avatar
Raymond Knopp committed
1150
  if (ulsch_harq->O_RI == 1) {
1151
    switch (Q_m) {
frtabu's avatar
frtabu committed
1152 1153 1154
      case 2:
        len_RI=2;
        break;
1155

frtabu's avatar
frtabu committed
1156 1157 1158
      case 4:
        len_RI=4;
        break;
1159

frtabu's avatar
frtabu committed
1160 1161 1162
      case 6:
        len_RI=6;
        break;
1163 1164 1165
    }
  }

Raymond Knopp's avatar
Raymond Knopp committed
1166
  if (ulsch_harq->O_RI > 1) {
1167 1168 1169 1170
    LOG_E(PHY,"ulsch_decoding: FATAL, RI cannot be more than 1 bit yet\n");
    return(-1);
  }

1171
  for (i=0; i<len_RI; i++)
Raymond Knopp's avatar
Raymond Knopp committed
1172
    ulsch_harq->q_RI[i] = 0;
1173

1174 1175 1176 1177
  if (frame_parms->Ncp == 0)
    columnset = cs_ri_normal;
  else
    columnset = cs_ri_extended;
1178 1179 1180 1181

  j=0;

  for (i=0; i<Qprime_RI; i++) {
1182
    r = Rmux_prime -1 - (i>>2);
1183 1184

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

1187 1188 1189 1190
    ytag[(r*Cmux) + columnset[j]] = LTE_NULL;
    j=(j+3)&3;
  }

1191
  //  printf("after RI2 c[%d] = %p\n",0,ulsch_harq->c[0]);
1192
  // CQI and Data bits
1193 1194 1195
  j=0;
  j2=0;

1196
  //  r=0;
1197 1198 1199
  if (Q_RI>0) {
    for (i=0; i<(Q_CQI/Q_m); i++) {
      while (ytag[j]==LTE_NULL) {
frtabu's avatar
frtabu committed
1200 1201
        j++;
        j2+=Q_m;
1202
      }
frtabu's avatar
frtabu committed
1203

1204
      for (q=0; q<Q_m; q++) {
frtabu's avatar
frtabu committed
1205 1206 1207 1208 1209 1210 1211 1212 1213
        //      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;
1214
      }
frtabu's avatar
frtabu committed
1215

1216 1217
      j2+=Q_m;
    }
frtabu's avatar
frtabu committed
1218

1219
    switch (Q_m) {
frtabu's avatar
frtabu committed
1220 1221 1222 1223 1224 1225
      case 2:
        for (iprime=0; iprime<G;) {
          while (ytag[j]==LTE_NULL) {
            j++;
            j2+=2;
          }
1226

1227 1228
          ulsch_harq->eE[iprime++] = y[j2++];
          ulsch_harq->eE[iprime++] = y[j2++];
frtabu's avatar
frtabu committed
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
        }

        break;

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

1240 1241 1242 1243
          ulsch_harq->eE[iprime++] = y[j2++];
          ulsch_harq->eE[iprime++] = y[j2++];
          ulsch_harq->eE[iprime++] = y[j2++];
          ulsch_harq->eE[iprime++] = y[j2++];
frtabu's avatar
frtabu committed
1244
        }
1245

frtabu's avatar
frtabu committed
1246 1247 1248 1249 1250 1251 1252 1253 1254
        break;

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

1255 1256 1257 1258 1259 1260
          ulsch_harq->eE[iprime++] = y[j2++];
          ulsch_harq->eE[iprime++] = y[j2++];
          ulsch_harq->eE[iprime++] = y[j2++];
          ulsch_harq->eE[iprime++] = y[j2++];
          ulsch_harq->eE[iprime++] = y[j2++];
          ulsch_harq->eE[iprime++] = y[j2++];
frtabu's avatar
frtabu committed
1261 1262 1263 1264
        }

        break;
    }
1265
  } // Q_RI>0
1266 1267 1268
  else {
    for (i=0; i<(Q_CQI/Q_m); i++) {
      for (q=0; q<Q_m; q++) {
frtabu's avatar
frtabu committed
1269 1270 1271 1272 1273 1274 1275 1276
        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;
1277
      }
frtabu's avatar
frtabu committed
1278

1279
      j2+=Q_m;
1280
    }
frtabu's avatar
frtabu committed
1281

1282
    /* To be improved according to alignment of j2
frtabu's avatar
frtabu committed
1283 1284
    #if defined(__x86_64__)||defined(__i386__)
    #ifndef __AVX2__
1285 1286
    for (iprime=0; iprime<G;iprime+=8,j2+=8)
      *((__m128i *)&ulsch_harq->e[iprime]) = *((__m128i *)&y[j2]);
frtabu's avatar
frtabu committed
1287
    #else
1288 1289
    for (iprime=0; iprime<G;iprime+=16,j2+=16)
      *((__m256i *)&ulsch_harq->e[iprime]) = *((__m256i *)&y[j2]);
frtabu's avatar
frtabu committed
1290 1291
    #endif
    #elif defined(__arm__)
1292 1293
    for (iprime=0; iprime<G;iprime+=8,j2+=8)
      *((int16x8_t *)&ulsch_harq->e[iprime]) = *((int16x8_t *)&y[j2]);
frtabu's avatar
frtabu committed
1294
    #endif
1295 1296
    */
    int16_t *yp,*ep;
frtabu's avatar
frtabu committed
1297

1298
    for (iprime=0,yp=&y[j2],ep=&ulsch_harq->eE[0];
frtabu's avatar
frtabu committed
1299 1300
         iprime<G;
         iprime+=8,j2+=8,ep+=8,yp+=8) {
1301 1302 1303 1304 1305 1306 1307 1308 1309
      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];
    }
1310
  }
1311

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

Raymond Knopp's avatar
Raymond Knopp committed
1318
  if (ulsch_harq->O_ACK == 1) {
1319 1320 1321 1322 1323 1324 1325
    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;
1326
  }
1327

Raymond Knopp's avatar
Raymond Knopp committed
1328
  if (ulsch_harq->O_ACK == 2) {
1329
    switch (Q_m) {
frtabu's avatar
frtabu committed
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346
      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;
1347
    }
1348

Raymond Knopp's avatar
Raymond Knopp committed
1349 1350 1351 1352
    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];
1353 1354

    if (metric_new > metric) {
Raymond Knopp's avatar
Raymond Knopp committed
1355 1356
      ulsch_harq->o_ACK[0]=0;
      ulsch_harq->o_ACK[1]=1;
1357 1358
      metric = metric_new;
    }
1359

Raymond Knopp's avatar
Raymond Knopp committed
1360
    metric_new = ulsch_harq->q_ACK[0]-ulsch_harq->q_ACK[1]+ulsch_harq->q_ACK[2];
1361 1362

    if (metric_new > metric) {
Raymond Knopp's avatar
Raymond Knopp committed
1363 1364
      ulsch_harq->o_ACK[0] = 1;
      ulsch_harq->o_ACK[1] = 0;
1365 1366
      metric = metric_new;
    }
1367

Raymond Knopp's avatar
Raymond Knopp committed
1368
    metric_new = -ulsch_harq->q_ACK[0]-ulsch_harq->q_ACK[1]-ulsch_harq->q_ACK[2];
1369 1370

    if (metric_new > metric) {
Raymond Knopp's avatar
Raymond Knopp committed
1371 1372
      ulsch_harq->o_ACK[0] = 0;
      ulsch_harq->o_ACK[1] = 0;
1373 1374 1375 1376 1377 1378
      metric = metric_new;
    }
  }

  // RI

1379
  // rank 1
Raymond Knopp's avatar
Raymond Knopp committed
1380
  if ((ulsch_harq->O_RI == 1) && (Qprime_RI > 0)) {
1381
    ulsch_harq->o_RI[0] = ((ulsch_harq->q_RI[0] + ulsch_harq->q_RI[Q_m/2]) > 0) ? 0 : 1;
1382
  }
1383

1384
  // CQI
1385
  //  printf("before cqi c[%d] = %p\n",0,ulsch_harq->c[0]);
1386
  ulsch_harq->cqi_crc_status = 0;
frtabu's avatar
frtabu committed
1387

1388
  if (Q_CQI>0) {
Raymond Knopp's avatar
Raymond Knopp committed
1389 1390
    memset((void *)&dummy_w_cc[0],0,3*(ulsch_harq->Or1+8+32));
    O_RCC = generate_dummy_w_cc(ulsch_harq->Or1+8,
1391
                                &dummy_w_cc[0]);
1392
    lte_rate_matching_cc_rx(O_RCC,
1393 1394 1395 1396
                            Q_CQI,
                            ulsch_harq->o_w,
                            dummy_w_cc,
                            ulsch_harq->q);
Raymond Knopp's avatar
Raymond Knopp committed
1397
    sub_block_deinterleaving_cc((unsigned int)(ulsch_harq->Or1+8),
1398 1399
                                &ulsch_harq->o_d[96],
                                &ulsch_harq->o_w[0]);
Cedric Roux's avatar
Cedric Roux committed
1400 1401
    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);
1402

Cedric Roux's avatar
Cedric Roux committed
1403
    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
1404
      ulsch_harq->cqi_crc_status = 1;
1405 1406

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

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

Raymond Knopp's avatar
Raymond Knopp committed
1412
    if (ulsch_harq->cqi_crc_status == 1)
Cedric Roux's avatar
Cedric Roux committed
1413
      printf("RX CQI CRC OK (%x)\n",extract_cqi_crc(ulsch_harq->o,ulsch_harq->Or1));
1414
    else
Cedric Roux's avatar
Cedric Roux committed
1415
      printf("RX CQI CRC NOT OK (%x)\n",extract_cqi_crc(ulsch_harq->o,ulsch_harq->Or1));
1416

1417 1418 1419
#endif
  }

Cedric Roux's avatar
Cedric Roux committed
1420
  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]);
1421
  // Do ULSCH Decoding for data portion
laurent's avatar
laurent committed
1422
  ret = ulsch_decoding_data_all(eNB,UE_id,harq_pid,llr8_flag);
1423
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,0);
1424 1425
  return(ret);
}