dlsch_coding.c 31.7 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 33 34 35 36 37 38

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

#include "PHY/defs.h"
#include "PHY/extern.h"
#include "PHY/CODING/defs.h"
#include "PHY/CODING/extern.h"
#include "PHY/CODING/lte_interleaver_inline.h"
#include "PHY/LTE_TRANSPORT/defs.h"
39
#include "PHY/LTE_TRANSPORT/proto.h"
Cedric Roux's avatar
Cedric Roux committed
40
#include "SCHED/defs.h"
41
#include "defs.h"
42
#include "UTIL/LOG/vcd_signal_dumper.h"
43 44
#include "UTIL/LOG/log.h"
#include <syscall.h>
45

46
//#define DEBUG_DLSCH_CODING
47 48 49
//#define DEBUG_DLSCH_FREE 1

/*
50 51 52
#define is_not_pilot(pilots,first_pilot,re) (pilots==0) || \
  ((pilots==1)&&(first_pilot==1)&&(((re>2)&&(re<6))||((re>8)&&(re<12)))) || \
  ((pilots==1)&&(first_pilot==0)&&(((re<3))||((re>5)&&(re<9)))) \
53 54 55 56
*/
#define is_not_pilot(pilots,first_pilot,re) (1)


57 58
void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch)
{
59 60 61 62 63
  int i;
  int r;

  if (dlsch) {
#ifdef DEBUG_DLSCH_FREE
64
    printf("Freeing dlsch %p\n",dlsch);
65
#endif
66 67

    for (i=0; i<dlsch->Mdlharq; i++) {
68
#ifdef DEBUG_DLSCH_FREE
69
      printf("Freeing dlsch process %d\n",i);
70
#endif
71

72 73
      if (dlsch->harq_processes[i]) {
#ifdef DEBUG_DLSCH_FREE
74
        printf("Freeing dlsch process %d (%p)\n",i,dlsch->harq_processes[i]);
75
#endif
76 77 78 79

        if (dlsch->harq_processes[i]->b) {
          free16(dlsch->harq_processes[i]->b,MAX_DLSCH_PAYLOAD_BYTES);
          dlsch->harq_processes[i]->b = NULL;
80
#ifdef DEBUG_DLSCH_FREE
81
          printf("Freeing dlsch process %d b (%p)\n",i,dlsch->harq_processes[i]->b);
82
#endif
83 84
        }

85
#ifdef DEBUG_DLSCH_FREE
86
        printf("Freeing dlsch process %d c (%p)\n",i,dlsch->harq_processes[i]->c);
87
#endif
88 89

        for (r=0; r<MAX_NUM_DLSCH_SEGMENTS; r++) {
90

91
#ifdef DEBUG_DLSCH_FREE
92
          printf("Freeing dlsch process %d c[%d] (%p)\n",i,r,dlsch->harq_processes[i]->c[r]);
93
#endif
94

95 96 97 98
          if (dlsch->harq_processes[i]->c[r]) {
            free16(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768);
            dlsch->harq_processes[i]->c[r] = NULL;
          }
99
          if (dlsch->harq_processes[i]->d[r]) {
100
            free16(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144)));
101 102
            dlsch->harq_processes[i]->d[r] = NULL;
          }
103

104 105 106
	}
	free16(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t));
	dlsch->harq_processes[i] = NULL;
107 108
      }
    }
109

110
    free16(dlsch,sizeof(LTE_eNB_DLSCH_t));
111
    dlsch = NULL;
112
    }
113

114 115
}

116
LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_t Nsoft,unsigned char N_RB_DL, uint8_t abstraction_flag, LTE_DL_FRAME_PARMS* frame_parms)
117
{
118 119

  LTE_eNB_DLSCH_t *dlsch;
120 121
  unsigned char exit_flag = 0,i,j,r,aa,layer;
  int re;
122
  unsigned char bw_scaling =1;
123 124 125

  switch (N_RB_DL) {
  case 6:
126 127
    bw_scaling =16;
    break;
128

129 130 131
  case 25:
    bw_scaling =4;
    break;
132 133

  case 50:
134 135
    bw_scaling =2;
    break;
136

137 138 139 140
  default:
    bw_scaling =1;
    break;
  }
141

142
  dlsch = (LTE_eNB_DLSCH_t *)malloc16(sizeof(LTE_eNB_DLSCH_t));
143

144 145 146 147
  if (dlsch) {
    bzero(dlsch,sizeof(LTE_eNB_DLSCH_t));
    dlsch->Kmimo = Kmimo;
    dlsch->Mdlharq = Mdlharq;
148
    dlsch->Mlimit = 8;
149
    dlsch->Nsoft = Nsoft;
150
    
151
    for (layer=0; layer<4; layer++) {
152
      dlsch->ue_spec_bf_weights[layer] = (int32_t**)malloc16(64*sizeof(int32_t*));
153
      
154
      for (aa=0; aa<64; aa++) {
155 156 157 158 159 160
	dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
	for (re=0;re<OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; re++) {
	  dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff;
	}
      }
    }
161

162 163
    // NOTE: THIS HAS TO BE REVISED FOR RU, commenting to remove memory leak !!!!!
    /*
164 165 166
     dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));
     for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
       dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
167

168
       }*/
169

170
    for (i=0; i<10; i++)
171 172
      dlsch->harq_ids[i] = Mdlharq;

173
    for (i=0; i<Mdlharq; i++) {
174
      dlsch->harq_processes[i] = (LTE_DL_eNB_HARQ_t *)malloc16(sizeof(LTE_DL_eNB_HARQ_t));
175
      LOG_T(PHY, "Required mem size %d (bw scaling %d), dlsch->harq_processes[%d] %p\n",
176 177
            MAX_DLSCH_PAYLOAD_BYTES/bw_scaling,bw_scaling, i,dlsch->harq_processes[i]);

178
      if (dlsch->harq_processes[i]) {
179 180 181 182 183 184 185
        bzero(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t));
        //    dlsch->harq_processes[i]->first_tx=1;
        dlsch->harq_processes[i]->b = (unsigned char*)malloc16(MAX_DLSCH_PAYLOAD_BYTES/bw_scaling);

        if (dlsch->harq_processes[i]->b) {
          bzero(dlsch->harq_processes[i]->b,MAX_DLSCH_PAYLOAD_BYTES/bw_scaling);
        } else {
186
          printf("Can't get b\n");
187 188 189 190 191 192
          exit_flag=1;
        }

        if (abstraction_flag==0) {
          for (r=0; r<MAX_NUM_DLSCH_SEGMENTS/bw_scaling; r++) {
            // account for filler in first segment and CRCs for multiple segment case
193
            dlsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(((r==0)?8:0) + 3+ 768);
194
            dlsch->harq_processes[i]->d[r] = (uint8_t*)malloc16((96+12+3+(3*6144)));
195 196 197
            if (dlsch->harq_processes[i]->c[r]) {
              bzero(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+ 768);
            } else {
198
              printf("Can't get c\n");
199 200
              exit_flag=2;
            }
201
            if (dlsch->harq_processes[i]->d[r]) {
202
              bzero(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144)));
203
            } else {
204
              printf("Can't get d\n");
205 206
              exit_flag=2;
            }
207
          }
208 209
        }
      } else {
210
        printf("Can't get harq_p %d\n",i);
211
        exit_flag=3;
212 213
      }
    }
214

215
    if (exit_flag==0) {
216 217 218
      for (i=0; i<Mdlharq; i++) {
        dlsch->harq_processes[i]->round=0;

219 220 221 222 223 224
	for (j=0; j<96; j++)
	  for (r=0; r<MAX_NUM_DLSCH_SEGMENTS/bw_scaling; r++) {
	    //      printf("dlsch->harq_processes[%d]->d[%d] %p\n",i,r,dlsch->harq_processes[i]->d[r]);
	    if (dlsch->harq_processes[i]->d[r])
	      dlsch->harq_processes[i]->d[r][j] = LTE_NULL;
	  }
225

226
      }
227

228 229 230
      return(dlsch);
    }
  }
231

232 233
  LOG_D(PHY,"new_eNB_dlsch exit flag %d, size of  %ld\n",
	exit_flag, sizeof(LTE_eNB_DLSCH_t));
234 235
  free_eNB_dlsch(dlsch);
  return(NULL);
236 237


238 239
}

240
void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch)
241
{
242 243 244

  unsigned char Mdlharq;
  unsigned char i,j,r;
245

246 247 248 249
  if (dlsch) {
    Mdlharq = dlsch->Mdlharq;
    dlsch->rnti = 0;
    dlsch->active = 0;
250
    dlsch->harq_mask = 0;
251 252

    for (i=0; i<10; i++)
253 254
      dlsch->harq_ids[i] = Mdlharq;

255
    for (i=0; i<Mdlharq; i++) {
256
      if (dlsch->harq_processes[i]) {
257 258 259 260
        //  dlsch->harq_processes[i]->Ndi    = 0;
        dlsch->harq_processes[i]->status = 0;
        dlsch->harq_processes[i]->round  = 0;

261 262 263 264
	for (j=0; j<96; j++)
	  for (r=0; r<MAX_NUM_DLSCH_SEGMENTS; r++)
	    if (dlsch->harq_processes[i]->d[r])
	      dlsch->harq_processes[i]->d[r][j] = LTE_NULL;
265

266 267 268 269 270
      }
    }
  }
}

271

272 273 274 275
int dlsch_encoding_2threads0(te_params *tep) {

  LTE_eNB_DLSCH_t *dlsch          = tep->dlsch;
  unsigned int G                  = tep->G;
276
  unsigned char harq_pid          = tep->harq_pid;
277 278

  unsigned short iind;
279

280 281
  unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb;
  unsigned int Kr=0,Kr_bytes,r,r_offset=0;
282
  //  unsigned short m=dlsch->harq_processes[harq_pid]->mcs;
283 284


285
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_FUNCTION_IN);
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341

  if (dlsch->harq_processes[harq_pid]->round == 0) {  // this is a new packet

    for (r=0; r<dlsch->harq_processes[harq_pid]->C>>1; r++) {

      if (r<dlsch->harq_processes[harq_pid]->Cminus)
        Kr = dlsch->harq_processes[harq_pid]->Kminus;
      else
        Kr = dlsch->harq_processes[harq_pid]->Kplus;

      Kr_bytes = Kr>>3;

      // get interleaver index for Turbo code (lookup in Table 5.1.3-3 36-212, V8.6 2009-03, p. 13-14)
      if (Kr_bytes<=64)
        iind = (Kr_bytes-5);
      else if (Kr_bytes <=128)
        iind = 59 + ((Kr_bytes-64)>>1);
      else if (Kr_bytes <= 256)
        iind = 91 + ((Kr_bytes-128)>>2);
      else if (Kr_bytes <= 768)
        iind = 123 + ((Kr_bytes-256)>>3);
      else {
        printf("dlsch_coding: Illegal codeword size %d!!!\n",Kr_bytes);
        return(-1);
      }



      threegpplte_turbo_encoder(dlsch->harq_processes[harq_pid]->c[r],
                                Kr>>3,
                                &dlsch->harq_processes[harq_pid]->d[r][96],
                                (r==0) ? dlsch->harq_processes[harq_pid]->F : 0,
                                f1f2mat_old[iind*2],   // f1 (see 36121-820, page 14)
                                f1f2mat_old[(iind*2)+1]  // f2 (see 36121-820, page 14)
                               );
      dlsch->harq_processes[harq_pid]->RTC[r] =
        sub_block_interleaving_turbo(4+(Kr_bytes*8),
                                     &dlsch->harq_processes[harq_pid]->d[r][96],
                                     dlsch->harq_processes[harq_pid]->w[r]);
    }

  }

  // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the
  // outputs for each code segment, see Section 5.1.5 p.20

  for (r=0; r<dlsch->harq_processes[harq_pid]->C>>1; r++) {
    r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r],
                                        G,  //G
                                        dlsch->harq_processes[harq_pid]->w[r],
                                        dlsch->harq_processes[harq_pid]->e+r_offset,
                                        dlsch->harq_processes[harq_pid]->C, // C
                                        dlsch->Nsoft,                    // Nsoft,
                                        dlsch->Mdlharq,
                                        dlsch->Kmimo,
                                        dlsch->harq_processes[harq_pid]->rvidx,
342
                                        dlsch->harq_processes[harq_pid]->Qm,
343 344
                                        dlsch->harq_processes[harq_pid]->Nl,
                                        r,
345 346
                                        nb_rb);
    //                                        m);                       // r
347 348
  }

349
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_FUNCTION_OUT);
350 351 352 353 354 355

  return(0);
}

extern int oai_exit;
void *te_thread(void *param) {
356 357
  pthread_setname_np( pthread_self(),"te processing");
  LOG_I(PHY,"thread te created id=%ld", syscall(__NR_gettid));
358 359 360 361

  eNB_proc_t *proc = &((te_params *)param)->eNB->proc;
  while (!oai_exit) {

362

363
    if (wait_on_condition(&proc->mutex_te,&proc->cond_te,&proc->instance_cnt_te,"te thread")<0) break;
364 365 366

    dlsch_encoding_2threads0((te_params*)param);

367

368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
    if (release_thread(&proc->mutex_te,&proc->instance_cnt_te,"te thread")<0) break;

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

  return(NULL);
}

int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
			    unsigned char *a,
			    uint8_t num_pdcch_symbols,
			    LTE_eNB_DLSCH_t *dlsch,
			    int frame,
			    uint8_t subframe,
			    time_stats_t *rm_stats,
			    time_stats_t *te_stats,
			    time_stats_t *i_stats)
{

  LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
  eNB_proc_t *proc = &eNB->proc;
  unsigned int G;
  unsigned int crc=1;
  unsigned short iind;

397
  unsigned char harq_pid = dlsch->harq_ids[subframe];
398 399 400 401
  unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb;
  unsigned int A;
  unsigned char mod_order;
  unsigned int Kr=0,Kr_bytes,r,r_offset=0;
402
  //  unsigned short m=dlsch->harq_processes[harq_pid]->mcs;
403 404 405 406

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);

  A = dlsch->harq_processes[harq_pid]->TBS; //6228
407
  mod_order = dlsch->harq_processes[harq_pid]->Qm;
408
  G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,dlsch->harq_processes[harq_pid]->mimo_mode==TM7?7:0);
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441


  if (dlsch->harq_processes[harq_pid]->round == 0) {  // this is a new packet

    // Add 24-bit crc (polynomial A) to payload
    crc = crc24a(a,
                 A)>>8;
    a[A>>3] = ((uint8_t*)&crc)[2];
    a[1+(A>>3)] = ((uint8_t*)&crc)[1];
    a[2+(A>>3)] = ((uint8_t*)&crc)[0];

    dlsch->harq_processes[harq_pid]->B = A+24;
    memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4);

    if (lte_segmentation(dlsch->harq_processes[harq_pid]->b,
                         dlsch->harq_processes[harq_pid]->c,
                         dlsch->harq_processes[harq_pid]->B,
                         &dlsch->harq_processes[harq_pid]->C,
                         &dlsch->harq_processes[harq_pid]->Cplus,
                         &dlsch->harq_processes[harq_pid]->Cminus,
                         &dlsch->harq_processes[harq_pid]->Kplus,
                         &dlsch->harq_processes[harq_pid]->Kminus,
                         &dlsch->harq_processes[harq_pid]->F)<0)
      return(-1);



    if (proc->instance_cnt_te==0) {
      printf("[eNB] TE thread busy\n");
      exit_fun("TE thread busy");
      pthread_mutex_unlock( &proc->mutex_te );
      return(-1);
    }
442

443
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
444 445 446 447 448
    ++proc->instance_cnt_te;

    proc->tep.eNB               = eNB;
    proc->tep.dlsch             = dlsch;
    proc->tep.G                 = G;
449
    proc->tep.harq_pid          = harq_pid;
450

451
    // wakeup worker to do second half segments
452 453 454 455 456 457 458 459
    if (pthread_cond_signal(&proc->cond_te) != 0) {
      printf("[eNB] ERROR pthread_cond_signal for te thread exit\n");
      exit_fun( "ERROR pthread_cond_signal" );
      return (-1);
    }

    pthread_mutex_unlock( &proc->mutex_te );

460
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
    for (r=dlsch->harq_processes[harq_pid]->C>>1; r<dlsch->harq_processes[harq_pid]->C; r++) {

      if (r<dlsch->harq_processes[harq_pid]->Cminus)
        Kr = dlsch->harq_processes[harq_pid]->Kminus;
      else
        Kr = dlsch->harq_processes[harq_pid]->Kplus;

      Kr_bytes = Kr>>3;

      // get interleaver index for Turbo code (lookup in Table 5.1.3-3 36-212, V8.6 2009-03, p. 13-14)
      if (Kr_bytes<=64)
        iind = (Kr_bytes-5);
      else if (Kr_bytes <=128)
        iind = 59 + ((Kr_bytes-64)>>1);
      else if (Kr_bytes <= 256)
        iind = 91 + ((Kr_bytes-128)>>2);
      else if (Kr_bytes <= 768)
        iind = 123 + ((Kr_bytes-256)>>3);
      else {
        printf("dlsch_coding: Illegal codeword size %d!!!\n",Kr_bytes);
        return(-1);
      }


      start_meas(te_stats);
      threegpplte_turbo_encoder(dlsch->harq_processes[harq_pid]->c[r],
                                Kr>>3,
                                &dlsch->harq_processes[harq_pid]->d[r][96],
                                (r==0) ? dlsch->harq_processes[harq_pid]->F : 0,
                                f1f2mat_old[iind*2],   // f1 (see 36121-820, page 14)
                                f1f2mat_old[(iind*2)+1]  // f2 (see 36121-820, page 14)
                               );
      stop_meas(te_stats);

      start_meas(i_stats);
      dlsch->harq_processes[harq_pid]->RTC[r] =
        sub_block_interleaving_turbo(4+(Kr_bytes*8),
                                     &dlsch->harq_processes[harq_pid]->d[r][96],
                                     dlsch->harq_processes[harq_pid]->w[r]);
      stop_meas(i_stats);
    }

  }
  else {

    proc->tep.eNB          = eNB;
    proc->tep.dlsch        = dlsch;
    proc->tep.G            = G;
509 510

    // wakeup worker to do second half segments
511 512 513 514 515 516 517 518 519 520
    if (pthread_cond_signal(&proc->cond_te) != 0) {
      printf("[eNB] ERROR pthread_cond_signal for te thread exit\n");
      exit_fun( "ERROR pthread_cond_signal" );
      return (-1);
    }
  }

  // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the
  // outputs for each code segment, see Section 5.1.5 p.20

521
  for (r=0,r_offset=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
522 523 524 525

    // get information for E for the segments that are handled by the worker thread
    if (r<(dlsch->harq_processes[harq_pid]->C>>1)) {
      int Nl=dlsch->harq_processes[harq_pid]->Nl;
526
      int Qm=dlsch->harq_processes[harq_pid]->Qm;
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
      int C = dlsch->harq_processes[harq_pid]->C;
      int Gp = G/Nl/Qm;
      int GpmodC = Gp%C;
      if (r < (C-(GpmodC)))
	r_offset += Nl*Qm * (Gp/C);
      else
	r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C));
    }
    else  {
      start_meas(rm_stats);
      r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r],
					  G,  //G
					  dlsch->harq_processes[harq_pid]->w[r],
					  dlsch->harq_processes[harq_pid]->e+r_offset,
					  dlsch->harq_processes[harq_pid]->C, // C
					  dlsch->Nsoft,                    // Nsoft,
					  dlsch->Mdlharq,
					  dlsch->Kmimo,
					  dlsch->harq_processes[harq_pid]->rvidx,
546
					  dlsch->harq_processes[harq_pid]->Qm,
547 548
					  dlsch->harq_processes[harq_pid]->Nl,
					  r,
549 550
					  nb_rb);
      //					  m);                       // r
551 552 553 554 555 556
      stop_meas(rm_stats);
    }
  }

  // wait for worker to finish

557 558
  wait_on_busy_condition(&proc->mutex_te,&proc->cond_te,&proc->instance_cnt_te,"te thread");

559 560 561 562 563 564 565 566

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);

  return(0);
}

int dlsch_encoding(PHY_VARS_eNB *eNB,
		   unsigned char *a,
567 568 569 570 571 572 573 574 575
                   uint8_t num_pdcch_symbols,
                   LTE_eNB_DLSCH_t *dlsch,
                   int frame,
                   uint8_t subframe,
                   time_stats_t *rm_stats,
                   time_stats_t *te_stats,
                   time_stats_t *i_stats)
{

576 577 578
  unsigned int G;
  unsigned int crc=1;
  unsigned short iind;
579

580
  LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
581
  unsigned char harq_pid = dlsch->harq_ids[subframe];
582
  unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb;
583
  unsigned int A;
584 585
  unsigned char mod_order;
  unsigned int Kr=0,Kr_bytes,r,r_offset=0;
586
  //  unsigned short m=dlsch->harq_processes[harq_pid]->mcs;
Xiwen JIANG's avatar
Xiwen JIANG committed
587
  uint8_t beamforming_mode=0;
588

589
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);
590

591 592
  A = dlsch->harq_processes[harq_pid]->TBS; //6228
  // printf("Encoder: A: %d\n",A);
593
  mod_order = dlsch->harq_processes[harq_pid]->Qm;
594

595
  if(dlsch->harq_processes[harq_pid]->mimo_mode == TM7)
Xiwen JIANG's avatar
Xiwen JIANG committed
596
    beamforming_mode = 7;
597
  else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM8)
Xiwen JIANG's avatar
Xiwen JIANG committed
598
    beamforming_mode = 8;
599
  else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM9_10)
Xiwen JIANG's avatar
Xiwen JIANG committed
600 601
    beamforming_mode = 9;
  G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,beamforming_mode);
602

603

604 605
  //  if (dlsch->harq_processes[harq_pid]->Ndi == 1) {  // this is a new packet
  if (dlsch->harq_processes[harq_pid]->round == 0) {  // this is a new packet
606 607 608
#ifdef DEBUG_DLSCH_CODING
  printf("encoding thinks this is a new packet \n");
#endif
609 610 611 612 613 614 615 616 617
    /*
    int i;
    printf("dlsch (tx): \n");
    for (i=0;i<(A>>3);i++)
      printf("%02x.",a[i]);
    printf("\n");
    */
    // Add 24-bit crc (polynomial A) to payload
    crc = crc24a(a,
618
                 A)>>8;
619 620 621
    a[A>>3] = ((uint8_t*)&crc)[2];
    a[1+(A>>3)] = ((uint8_t*)&crc)[1];
    a[2+(A>>3)] = ((uint8_t*)&crc)[0];
622 623 624 625 626
    //    printf("CRC %x (A %d)\n",crc,A);

    dlsch->harq_processes[harq_pid]->B = A+24;
    //    dlsch->harq_processes[harq_pid]->b = a;
    memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4);
627

628
    if (lte_segmentation(dlsch->harq_processes[harq_pid]->b,
629 630 631 632 633 634 635 636
                         dlsch->harq_processes[harq_pid]->c,
                         dlsch->harq_processes[harq_pid]->B,
                         &dlsch->harq_processes[harq_pid]->C,
                         &dlsch->harq_processes[harq_pid]->Cplus,
                         &dlsch->harq_processes[harq_pid]->Cminus,
                         &dlsch->harq_processes[harq_pid]->Kplus,
                         &dlsch->harq_processes[harq_pid]->Kminus,
                         &dlsch->harq_processes[harq_pid]->F)<0)
637
      return(-1);
638 639

    for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
640

641
      if (r<dlsch->harq_processes[harq_pid]->Cminus)
642
        Kr = dlsch->harq_processes[harq_pid]->Kminus;
643
      else
644 645
        Kr = dlsch->harq_processes[harq_pid]->Kplus;

646
      Kr_bytes = Kr>>3;
647

648 649
      // get interleaver index for Turbo code (lookup in Table 5.1.3-3 36-212, V8.6 2009-03, p. 13-14)
      if (Kr_bytes<=64)
650
        iind = (Kr_bytes-5);
651
      else if (Kr_bytes <=128)
652
        iind = 59 + ((Kr_bytes-64)>>1);
653
      else if (Kr_bytes <= 256)
654
        iind = 91 + ((Kr_bytes-128)>>2);
655
      else if (Kr_bytes <= 768)
656
        iind = 123 + ((Kr_bytes-256)>>3);
657
      else {
658
        printf("dlsch_coding: Illegal codeword size %d!!!\n",Kr_bytes);
659
        return(-1);
660
      }
661 662


663 664 665
#ifdef DEBUG_DLSCH_CODING
      printf("Generating Code Segment %d (%d bits)\n",r,Kr);
      // generate codewords
666

667 668 669 670
      printf("bits_per_codeword (Kr)= %d, A %d\n",Kr,A);
      printf("N_RB = %d\n",nb_rb);
      printf("Ncp %d\n",frame_parms->Ncp);
      printf("mod_order %d\n",mod_order);
671
#endif
672 673 674


#ifdef DEBUG_DLSCH_CODING
675
      printf("Encoding ... iind %d f1 %d, f2 %d\n",iind,f1f2mat_old[iind*2],f1f2mat_old[(iind*2)+1]);
676 677 678
#endif
      start_meas(te_stats);
      threegpplte_turbo_encoder(dlsch->harq_processes[harq_pid]->c[r],
679 680 681 682 683 684
                                Kr>>3,
                                &dlsch->harq_processes[harq_pid]->d[r][96],
                                (r==0) ? dlsch->harq_processes[harq_pid]->F : 0,
                                f1f2mat_old[iind*2],   // f1 (see 36121-820, page 14)
                                f1f2mat_old[(iind*2)+1]  // f2 (see 36121-820, page 14)
                               );
685 686
      stop_meas(te_stats);
#ifdef DEBUG_DLSCH_CODING
687

688
      if (r==0)
689 690
        write_output("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[r][96],(3*8*Kr_bytes)+12,1,4);

691 692
#endif
      start_meas(i_stats);
693 694 695 696
      dlsch->harq_processes[harq_pid]->RTC[r] =
        sub_block_interleaving_turbo(4+(Kr_bytes*8),
                                     &dlsch->harq_processes[harq_pid]->d[r][96],
                                     dlsch->harq_processes[harq_pid]->w[r]);
697 698
      stop_meas(i_stats);
    }
699

700 701 702 703 704
  }

  // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the
  // outputs for each code segment, see Section 5.1.5 p.20

705
  for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
706
#ifdef DEBUG_DLSCH_CODING
707
    printf("Rate Matching, Code segment %d (coded bits (G) %d,unpunctured/repeated bits per code segment %d,mod_order %d, nb_rb %d)...\n",
708 709 710 711
        r,
        G,
        Kr*3,
        mod_order,nb_rb);
712 713 714
#endif

    start_meas(rm_stats);
715 716 717
#ifdef DEBUG_DLSCH_CODING
  printf("rvidx in encoding = %d\n", dlsch->harq_processes[harq_pid]->rvidx);
#endif
718
    r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r],
719 720 721 722
                                        G,  //G
                                        dlsch->harq_processes[harq_pid]->w[r],
                                        dlsch->harq_processes[harq_pid]->e+r_offset,
                                        dlsch->harq_processes[harq_pid]->C, // C
723
                                        dlsch->Nsoft,                    // Nsoft,
724 725 726
                                        dlsch->Mdlharq,
                                        dlsch->Kmimo,
                                        dlsch->harq_processes[harq_pid]->rvidx,
727
                                        dlsch->harq_processes[harq_pid]->Qm,
728 729
                                        dlsch->harq_processes[harq_pid]->Nl,
                                        r,
730 731
                                        nb_rb);
					//                                        m);                       // r
732 733
    stop_meas(rm_stats);
#ifdef DEBUG_DLSCH_CODING
734

735
    if (r==dlsch->harq_processes[harq_pid]->C-1)
736
      write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->e,r_offset,1,4);
737

738 739
#endif
  }
740

741
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
742

743 744 745
  return(0);
}

746 747

int dlsch_encoding_SIC(PHY_VARS_UE *ue,
748 749 750 751 752 753 754 755
		       unsigned char *a,
		       uint8_t num_pdcch_symbols,
		       LTE_eNB_DLSCH_t *dlsch,
		       int frame,
		       uint8_t subframe,
		       time_stats_t *rm_stats,
		       time_stats_t *te_stats,
		       time_stats_t *i_stats)
756
{
757
  
758 759 760 761 762
  unsigned int G;
  unsigned int crc=1;
  unsigned short iind;

  LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
763
  unsigned char harq_pid = ue->dlsch[subframe&2][0][0]->rnti;
764 765 766 767
  unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb;
  unsigned int A;
  unsigned char mod_order;
  unsigned int Kr=0,Kr_bytes,r,r_offset=0;
768
  //  unsigned short m=dlsch->harq_processes[harq_pid]->mcs;
769 770 771 772 773 774
  uint8_t beamforming_mode=0;

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);

  A = dlsch->harq_processes[harq_pid]->TBS; //6228
  // printf("Encoder: A: %d\n",A);
775
  mod_order = dlsch->harq_processes[harq_pid]->Qm;
776 777 778 779 780 781 782 783 784 785 786 787

  if(dlsch->harq_processes[harq_pid]->mimo_mode == TM7)
    beamforming_mode = 7;
  else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM8)
    beamforming_mode = 8;
  else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM9_10)
    beamforming_mode = 9;
  G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,beamforming_mode);


  //  if (dlsch->harq_processes[harq_pid]->Ndi == 1) {  // this is a new packet
  if (dlsch->harq_processes[harq_pid]->round == 0) {  // this is a new packet
788 789 790
#ifdef DEBUG_DLSCH_CODING
  printf("SIC encoding thinks this is a new packet \n");
#endif
791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
    /*
    int i;
    printf("dlsch (tx): \n");
    for (i=0;i<(A>>3);i++)
      printf("%02x.",a[i]);
    printf("\n");
    */
    // Add 24-bit crc (polynomial A) to payload
    crc = crc24a(a,
                 A)>>8;
    a[A>>3] = ((uint8_t*)&crc)[2];
    a[1+(A>>3)] = ((uint8_t*)&crc)[1];
    a[2+(A>>3)] = ((uint8_t*)&crc)[0];
    //    printf("CRC %x (A %d)\n",crc,A);

    dlsch->harq_processes[harq_pid]->B = A+24;
    //    dlsch->harq_processes[harq_pid]->b = a;
    memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4);

    if (lte_segmentation(dlsch->harq_processes[harq_pid]->b,
                         dlsch->harq_processes[harq_pid]->c,
                         dlsch->harq_processes[harq_pid]->B,
                         &dlsch->harq_processes[harq_pid]->C,
                         &dlsch->harq_processes[harq_pid]->Cplus,
                         &dlsch->harq_processes[harq_pid]->Cminus,
                         &dlsch->harq_processes[harq_pid]->Kplus,
                         &dlsch->harq_processes[harq_pid]->Kminus,
                         &dlsch->harq_processes[harq_pid]->F)<0)
      return(-1);

    for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {

      if (r<dlsch->harq_processes[harq_pid]->Cminus)
        Kr = dlsch->harq_processes[harq_pid]->Kminus;
      else
        Kr = dlsch->harq_processes[harq_pid]->Kplus;

      Kr_bytes = Kr>>3;

      // get interleaver index for Turbo code (lookup in Table 5.1.3-3 36-212, V8.6 2009-03, p. 13-14)
      if (Kr_bytes<=64)
        iind = (Kr_bytes-5);
      else if (Kr_bytes <=128)
        iind = 59 + ((Kr_bytes-64)>>1);
      else if (Kr_bytes <= 256)
        iind = 91 + ((Kr_bytes-128)>>2);
      else if (Kr_bytes <= 768)
        iind = 123 + ((Kr_bytes-256)>>3);
      else {
        printf("dlsch_coding: Illegal codeword size %d!!!\n",Kr_bytes);
        return(-1);
      }


#ifdef DEBUG_DLSCH_CODING
      printf("Generating Code Segment %d (%d bits)\n",r,Kr);
      // generate codewords

      printf("bits_per_codeword (Kr)= %d, A %d\n",Kr,A);
      printf("N_RB = %d\n",nb_rb);
      printf("Ncp %d\n",frame_parms->Ncp);
      printf("mod_order %d\n",mod_order);
#endif


#ifdef DEBUG_DLSCH_CODING
      printf("Encoding ... iind %d f1 %d, f2 %d\n",iind,f1f2mat_old[iind*2],f1f2mat_old[(iind*2)+1]);
#endif
      start_meas(te_stats);
      threegpplte_turbo_encoder(dlsch->harq_processes[harq_pid]->c[r],
                                Kr>>3,
                                &dlsch->harq_processes[harq_pid]->d[r][96],
                                (r==0) ? dlsch->harq_processes[harq_pid]->F : 0,
                                f1f2mat_old[iind*2],   // f1 (see 36121-820, page 14)
                                f1f2mat_old[(iind*2)+1]  // f2 (see 36121-820, page 14)
                               );
      stop_meas(te_stats);
#ifdef DEBUG_DLSCH_CODING

      if (r==0)
        write_output("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[r][96],(3*8*Kr_bytes)+12,1,4);

#endif
      start_meas(i_stats);
      dlsch->harq_processes[harq_pid]->RTC[r] =
        sub_block_interleaving_turbo(4+(Kr_bytes*8),
                                     &dlsch->harq_processes[harq_pid]->d[r][96],
                                     dlsch->harq_processes[harq_pid]->w[r]);
      stop_meas(i_stats);
    }

  }

  // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the
  // outputs for each code segment, see Section 5.1.5 p.20

  for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
#ifdef DEBUG_DLSCH_CODING
    printf("Rate Matching, Code segment %d (coded bits (G) %d,unpunctured/repeated bits per code segment %d,mod_order %d, nb_rb %d)...\n",
        r,
        G,
        Kr*3,
        mod_order,nb_rb);
#endif

    start_meas(rm_stats);
897 898 899
#ifdef DEBUG_DLSCH_CODING
    printf("rvidx in SIC encoding = %d\n", dlsch->harq_processes[harq_pid]->rvidx);
#endif
900 901 902 903 904 905 906 907 908
    r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r],
                                        G,  //G
                                        dlsch->harq_processes[harq_pid]->w[r],
                                        dlsch->harq_processes[harq_pid]->e+r_offset,
                                        dlsch->harq_processes[harq_pid]->C, // C
                                        dlsch->Nsoft,                    // Nsoft,
                                        dlsch->Mdlharq,
                                        dlsch->Kmimo,
                                        dlsch->harq_processes[harq_pid]->rvidx,
909
                                        dlsch->harq_processes[harq_pid]->Qm,
910 911
                                        dlsch->harq_processes[harq_pid]->Nl,
                                        r,
912 913
                                        nb_rb);
    //                                        m);                       // r
914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
    stop_meas(rm_stats);
#ifdef DEBUG_DLSCH_CODING

    if (r==dlsch->harq_processes[harq_pid]->C-1)
      write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->e,r_offset,1,4);

#endif
  }

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);

  return(0);
}




931