text: /*
   * 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
   * the OAI Public License, Version 1.1  (the "License"); you may not use this file
   * 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
   */
  
  /*! \file PHY/LTE_TRANSPORT/dci_tools.c
   * \brief PHY Support routines (eNB/UE) for filling PDSCH/PUSCH/DLSCH/ULSCH data structures based on DCI PDUs generated by eNB MAC scheduler.
   * \author R. Knopp
   * \date 2011
   * \version 0.1
   * \company Eurecom
   * \email: knopp@eurecom.fr
   * \note
   * \warning
   */
  
  #include "PHY/defs_eNB.h"
  #include "PHY/phy_extern.h"
  #include "SCHED/sched_eNB.h"
  #ifdef DEBUG_DCI_TOOLS
  #include "PHY/phy_vars.h"
  #endif
  #include "assertions.h"
  #include "nfapi_interface.h"
  
  //#define DEBUG_HARQ
  
  
  
  
  #include "LAYER2/MAC/mac.h"
  
  //#define DEBUG_DCI
  #include "dci_tools_common_extern.h"
  #include "transport_proto.h"
  
  //#undef LOG_D
  //#define LOG_D(A,B...) printf(B)
  
  int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type)
  {
    uint16_t i;
    int16_t first_free_index=-1;
  
    AssertFatal(eNB!=NULL,"eNB is null\n");
    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
      AssertFatal(eNB->dlsch[i]!=NULL,"eNB->dlsch[%d] is null\n",i);
      AssertFatal(eNB->dlsch[i]!=NULL,"eNB->dlsch[%d][0] is null\n",i);
      LOG_D(PHY,"searching for rnti %x : UE index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i,eNB->dlsch[i][0]->harq_mask,eNB->dlsch[i][0]->rnti,first_free_index);
      if ((eNB->dlsch[i][0]->harq_mask >0) &&
          (eNB->dlsch[i][0]->rnti==rnti))       return i;
      else if ((eNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i;
    }
    if (type == SEARCH_EXIST)
      return -1;
    if (first_free_index != -1)
      eNB->dlsch[first_free_index][0]->rnti = 0;
    return first_free_index;
  }
  
  
  int16_t find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type)
  {
    uint16_t i;
    int16_t first_free_index=-1;
  
    AssertFatal(eNB!=NULL,"eNB is null\n");
    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
      AssertFatal(eNB->ulsch[i]!=NULL,"eNB->ulsch[%d] is null\n",i);
      if ((eNB->ulsch[i]->harq_mask >0) &&
          (eNB->ulsch[i]->rnti==rnti))       return i;
      else if ((eNB->ulsch[i]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i;
    }
    if (type == SEARCH_EXIST)
      return -1;
    if (first_free_index != -1)
      eNB->ulsch[first_free_index]->rnti = 0;
    return first_free_index;
  }
  
  
  
  
  
  void fill_pdcch_order(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,DCI_ALLOC_t *dci_alloc,nfapi_dl_config_dci_dl_pdu *pdu)
  {
    LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
    uint8_t        *dci_pdu = &dci_alloc->dci_pdu[0];
    nfapi_dl_config_dci_dl_pdu_rel8_t *rel8 = &pdu->dci_dl_pdu_rel8;
  
    dci_alloc->firstCCE = rel8->cce_idx;
    dci_alloc->L = rel8->aggregation_level;
    dci_alloc->rnti = rel8->rnti;
    dci_alloc->harq_pid = rel8->harq_process;
    dci_alloc->ra_flag = 0;
    dci_alloc->format = format1A;
  
    LOG_D (PHY, "NFAPI: DCI format %d, nCCE %d, L %d, rnti %x,harq_pid %d\n", rel8->dci_format, rel8->cce_idx, rel8->aggregation_level, rel8->rnti, rel8->harq_process);
  
    switch (fp->N_RB_DL) {
    case 6:
      if (fp->frame_type == TDD) {
  
        dci_alloc->dci_length                         = sizeof_DCI1A_1_5MHz_TDD_1_6_t;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->type     = 1;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->vrb_type = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->mcs      = rel8->mcs_1;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->TPC      = rel8->tpc;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid = rel8->harq_process;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
        ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->padding  = 0;
      } else {
        dci_alloc->dci_length                         = sizeof_DCI1A_1_5MHz_FDD_t;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->type         = 1;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->vrb_type     = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->mcs          = rel8->mcs_1;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->ndi          = rel8->new_data_indicator_1;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->rballoc      = rel8->resource_block_coding;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->rv           = rel8->redundancy_version_1;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->TPC          = rel8->tpc;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->harq_pid     = rel8->harq_process;
        ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->padding      = 0;
  
        //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      }
      break;
    case 25:
      if (fp->frame_type == TDD) {
  
        dci_alloc->dci_length                         = sizeof_DCI1A_5MHz_TDD_1_6_t;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->type       = 1;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->vrb_type   = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->mcs        = rel8->mcs_1;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->ndi        = rel8->new_data_indicator_1;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->rballoc    = rel8->resource_block_coding;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->rv         = rel8->redundancy_version_1;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->TPC        = rel8->tpc;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid   = rel8->harq_process;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->dai        = rel8->downlink_assignment_index;
        ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->padding    = 0;
         //        printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      } else {
        dci_alloc->dci_length                         = sizeof_DCI1A_5MHz_FDD_t;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->type           = 1;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->vrb_type       = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->mcs            = rel8->mcs_1;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->ndi            = rel8->new_data_indicator_1;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->rballoc        = rel8->resource_block_coding;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->rv             = rel8->redundancy_version_1;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->TPC            = rel8->tpc;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->harq_pid       = rel8->harq_process;
        ((DCI1A_5MHz_FDD_t *)dci_pdu)->padding        = 0;
        //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      }
      break;
    case 50:
      if (fp->frame_type == TDD) {
  
        dci_alloc->dci_length                         = sizeof_DCI1A_10MHz_TDD_1_6_t;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->type      = 1;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->vrb_type  = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->mcs       = rel8->mcs_1;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->ndi       = rel8->new_data_indicator_1;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->rv        = rel8->redundancy_version_1;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->TPC       = rel8->tpc;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->harq_pid  = rel8->harq_process;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
        ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->padding   = 0;
        //        printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      } else {
        dci_alloc->dci_length                         = sizeof_DCI1A_10MHz_FDD_t;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->type          = 1;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->vrb_type      = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->mcs           = rel8->mcs_1;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->ndi           = rel8->new_data_indicator_1;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->rv            = rel8->redundancy_version_1;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
        ((DCI1A_10MHz_FDD_t *)dci_pdu)->padding       = 0;
  
        //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      }
      break;
    case 100:
      if (fp->frame_type == TDD) {
  
        dci_alloc->dci_length                         = sizeof_DCI1A_20MHz_TDD_1_6_t;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->type      = 1;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->vrb_type  = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->mcs       = rel8->mcs_1;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->ndi       = rel8->new_data_indicator_1;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->rv        = rel8->redundancy_version_1;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->TPC       = rel8->tpc;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->harq_pid  = rel8->harq_process;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
        ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->padding   = 0;
        //        printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      } else {
        dci_alloc->dci_length                         = sizeof_DCI1A_20MHz_FDD_t;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->type          = 1;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->vrb_type      = rel8->virtual_resource_block_assignment_flag;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->mcs           = rel8->mcs_1;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->ndi           = rel8->new_data_indicator_1;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->rv            = rel8->redundancy_version_1;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
        ((DCI1A_20MHz_FDD_t *)dci_pdu)->padding       = 0;
        //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
      }
      break;
    }
  
  
    LOG_T(PHY,"%d.%d: DCI 1A: rnti %x, PDCCH order to do PRACH\n",
          proc->frame_tx, proc->subframe_tx, rel8->rnti);
  }
  
  void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t *proc,DCI_ALLOC_t *dci_alloc,nfapi_dl_config_dci_dl_pdu *pdu)
  {
    LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
    uint8_t        *dci_pdu = &dci_alloc->dci_pdu[0];
    nfapi_dl_config_dci_dl_pdu_rel8_t *rel8 = &pdu->dci_dl_pdu_rel8;
  
    /* check if this is a DCI 1A PDCCH order for RAPROC */
    if (rel8->dci_format == NFAPI_DL_DCI_FORMAT_1A && rel8->rnti_type == 1) {
      int             full_rb;
      switch (fp->N_RB_DL) {
      case 6:
        full_rb = 63;
        break;
      case 25:
        full_rb = 511;
        break;
      case 50:
        full_rb = 2047;
        break;
      case 100:
        full_rb = 8191;
        break;
      default:
        abort ();
      }
      if (rel8->resource_block_coding == full_rb)
        return fill_pdcch_order (eNB, proc, dci_alloc, pdu);
    }
  
  
    LTE_eNB_DLSCH_t *dlsch0=NULL,*dlsch1=NULL;
    LTE_DL_eNB_HARQ_t *dlsch0_harq=NULL,*dlsch1_harq=NULL;
    int beamforming_mode = 0;
    int UE_id=-1;
    int NPRB;
    int TB0_active;
    int TB1_active;
    uint16_t DL_pmi_single=0; // This should be taken from DLSCH parameters for PUSCH precoding
    uint8_t I_mcs = 0;
   
  
    dci_alloc->firstCCE = rel8->cce_idx;
    dci_alloc->L = rel8->aggregation_level;
    dci_alloc->rnti = rel8->rnti;
    dci_alloc->harq_pid = rel8->harq_process;
    dci_alloc->ra_flag = 0;
  
  
    LOG_D(PHY,"NFAPI: SFN/SF:%04d%d proc:TX:[SFN/SF:%04d%d] DCI format %d, nCCE %d, L %d, rnti %x, harq_pid %d\n",
  	frame,subframe,proc->frame_tx,proc->subframe_tx,rel8->dci_format,rel8->cce_idx,rel8->aggregation_level,rel8->rnti,rel8->harq_process);
    if ((rel8->rnti_type == 2 ) && (rel8->rnti != SI_RNTI) && (rel8->rnti != P_RNTI)) dci_alloc->ra_flag = 1;
  
    UE_id = find_dlsch(rel8->rnti,eNB,SEARCH_EXIST_OR_FREE);
    if( (UE_id<0) || (UE_id>=NUMBER_OF_UE_MAX) ){
      LOG_E(PHY,"illegal UE_id found!!! rnti %04x UE_id %d\n",rel8->rnti,UE_id);
      return;
    }
    //AssertFatal(UE_id!=-1,"no free or exiting dlsch_context\n");
    //AssertFatal(UE_id<NUMBER_OF_UE_MAX,"returned UE_id %d >= %d(NUMBER_OF_UE_MAX)\n",UE_id,NUMBER_OF_UE_MAX);
    dlsch0 = eNB->dlsch[UE_id][0];
    dlsch1 = eNB->dlsch[UE_id][1];
  
    dlsch0->ue_type = 0;
    dlsch1->ue_type = 0; 
    beamforming_mode                          = eNB->transmission_mode[(uint8_t)UE_id]<7?0:eNB->transmission_mode[(uint8_t)UE_id];
    dlsch0_harq                               = dlsch0->harq_processes[rel8->harq_process];
    dlsch0_harq->codeword                     = 0;
    dlsch1_harq                               = dlsch1->harq_processes[rel8->harq_process];
    dlsch1_harq->codeword                     = 1;
    dlsch0->subframe_tx[subframe]             = 1;
  
    LOG_D(PHY,"NFAPI: SFN/SF:%04d%d proc:TX:SFN/SF:%04d%d dlsch0[rnti:%x harq_mask:%04x] dci_pdu[rnti:%x rnti_type:%d harq_process:%d ndi1:%d] dlsch0_harq[round:%d harq_mask:%x ndi:%d]\n", 
        frame,subframe,
        proc->frame_tx,proc->subframe_tx,
        dlsch0->rnti,dlsch0->harq_mask,
        rel8->rnti, rel8->rnti_type, rel8->harq_process, rel8->new_data_indicator_1,
        dlsch0_harq->round, dlsch0->harq_mask, dlsch0_harq->ndi);
  
    if (dlsch0->rnti != rel8->rnti) { // if rnti of dlsch is not the same as in the config, this is a new entry
      dlsch0_harq->round=0;
      dlsch0->harq_mask=0;
    }
    if ((dlsch0->harq_mask & (1 << rel8->harq_process)) > 0) {
      if (rel8->new_data_indicator_1 != dlsch0_harq->ndi)
        dlsch0_harq->round = 0;
    } else {                      // process is inactive, so activate and set round to 0
      dlsch0_harq->round = 0;
    }
    dlsch0_harq->ndi = rel8->new_data_indicator_1;
  
  
  #ifdef PHY_TX_THREAD
    dlsch0->active[subframe]        = 1;
  #else
    dlsch0->active        = 1;
  #endif
    if (rel8->rnti_type == 2)
        dlsch0_harq->round    = 0;
  
    LOG_D(PHY,"NFAPI: rel8[rnti %x dci_format %d harq_process %d ndi1 %d rnti type %d] dlsch0[rnti %x harq_mask %x] dlsch0_harq[round %d ndi %d]\n",
        rel8->rnti,rel8->dci_format,rel8->harq_process, rel8->new_data_indicator_1, rel8->rnti_type,
        dlsch0->rnti,dlsch0->harq_mask,
        dlsch0_harq->round,dlsch0_harq->ndi
        );
  
    switch (rel8->dci_format) {
  
    case NFAPI_DL_DCI_FORMAT_1A:
  
      AssertFatal(rel8->resource_block_coding < 8192, "SFN/SF:%04d%d proc:TX:SFN/SF:%04d%d: rel8->resource_block_coding (%p) %u >= 8192 (rnti %x, rnti_type %d, format %d, harq_id %d\n",
                  frame,subframe,proc->frame_tx,subframe,
                  &rel8->resource_block_coding,rel8->resource_block_coding,rel8->rnti,rel8->rnti_type,rel8->dci_format,rel8->harq_process);
    
      dci_alloc->format = format1A;
  
      switch (fp->N_RB_DL) {
      case 6:
        if (fp->frame_type == TDD) {
  
  	dci_alloc->dci_length                         = sizeof_DCI1A_1_5MHz_TDD_1_6_t; 
          ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->type     = 1;
          ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->vrb_type = rel8->virtual_resource_block_assignment_flag;
          ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->mcs      = rel8->mcs_1;
          ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
          ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
          ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
          ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->TPC      = rel8->tpc;
          ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid = rel8->harq_process;
          ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
          ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->padding  = 0;
  	
        } else {
  	dci_alloc->dci_length                         = sizeof_DCI1A_1_5MHz_FDD_t; 
  	((DCI1A_1_5MHz_FDD_t *)dci_pdu)->type         = 1;
          ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->vrb_type     = rel8->virtual_resource_block_assignment_flag;
          ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->mcs          = rel8->mcs_1;
          ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->ndi          = rel8->new_data_indicator_1;
          ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->rballoc      = rel8->resource_block_coding;
          ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->rv           = rel8->redundancy_version_1;
          ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->TPC          = rel8->tpc;
          ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->harq_pid     = rel8->harq_process;
          ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->padding      = 0;
  
          //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        }
        AssertFatal (rel8->virtual_resource_block_assignment_flag == LOCALIZED, "Distributed RB allocation not done yet\n");
        dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT6[rel8->resource_block_coding];
        dlsch0_harq->vrb_type = rel8->virtual_resource_block_assignment_flag;
        dlsch0_harq->nb_rb = RIV2nb_rb_LUT6[rel8->resource_block_coding]; //NPRB;
        break;
      case 25:
        if (fp->frame_type == TDD) {
  	dci_alloc->dci_length                         = sizeof_DCI1A_5MHz_TDD_1_6_t; 
          ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->type       = 1;
          ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->vrb_type   = rel8->virtual_resource_block_assignment_flag;
          ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->mcs        = rel8->mcs_1;
          ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->ndi        = rel8->new_data_indicator_1;
          ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->rballoc    = rel8->resource_block_coding;
          ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->rv         = rel8->redundancy_version_1;
          ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->TPC        = rel8->tpc;
          ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid   = rel8->harq_process;
          ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->dai        = rel8->downlink_assignment_index;
          ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->padding    = 0;
           //        printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                         = sizeof_DCI1A_5MHz_FDD_t; 
  	((DCI1A_5MHz_FDD_t *)dci_pdu)->type           = 1;
          ((DCI1A_5MHz_FDD_t *)dci_pdu)->vrb_type       = rel8->virtual_resource_block_assignment_flag;
          ((DCI1A_5MHz_FDD_t *)dci_pdu)->mcs            = rel8->mcs_1;
          ((DCI1A_5MHz_FDD_t *)dci_pdu)->ndi            = rel8->new_data_indicator_1;
          ((DCI1A_5MHz_FDD_t *)dci_pdu)->rballoc        = rel8->resource_block_coding;
          ((DCI1A_5MHz_FDD_t *)dci_pdu)->rv             = rel8->redundancy_version_1;
          ((DCI1A_5MHz_FDD_t *)dci_pdu)->TPC            = rel8->tpc;
          ((DCI1A_5MHz_FDD_t *)dci_pdu)->harq_pid       = rel8->harq_process;
          ((DCI1A_5MHz_FDD_t *)dci_pdu)->padding        = 0;
          //      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        }
        AssertFatal (rel8->virtual_resource_block_assignment_flag == LOCALIZED, "Distributed RB allocation not done yet\n");
        dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT25[rel8->resource_block_coding];
        dlsch0_harq->vrb_type = rel8->virtual_resource_block_assignment_flag;
        dlsch0_harq->nb_rb = RIV2nb_rb_LUT25[rel8->resource_block_coding];        //NPRB;
        break;
      case 50:
        if (fp->frame_type == TDD) {
  
  	dci_alloc->dci_length                         = sizeof_DCI1A_10MHz_TDD_1_6_t; 
          ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->type      = 1;
          ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->vrb_type  = rel8->virtual_resource_block_assignment_flag;
          ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->mcs       = rel8->mcs_1;
          ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->ndi       = rel8->new_data_indicator_1;
          ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
          ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->rv        = rel8->redundancy_version_1;
          ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->TPC       = rel8->tpc;
          ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->harq_pid  = rel8->harq_process;
          ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
          ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->padding   = 0;
          //        printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                         = sizeof_DCI1A_10MHz_FDD_t; 
  	((DCI1A_10MHz_FDD_t *)dci_pdu)->type          = 1;
          ((DCI1A_10MHz_FDD_t *)dci_pdu)->vrb_type      = rel8->virtual_resource_block_assignment_flag;
          ((DCI1A_10MHz_FDD_t *)dci_pdu)->mcs           = rel8->mcs_1;
          ((DCI1A_10MHz_FDD_t *)dci_pdu)->ndi           = rel8->new_data_indicator_1;
          ((DCI1A_10MHz_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
          ((DCI1A_10MHz_FDD_t *)dci_pdu)->rv            = rel8->redundancy_version_1;
          ((DCI1A_10MHz_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
          ((DCI1A_10MHz_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
          ((DCI1A_10MHz_FDD_t *)dci_pdu)->padding       = 0;
  	//      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        }
        AssertFatal (rel8->virtual_resource_block_assignment_flag == LOCALIZED, "Distributed RB allocation not done yet\n");
        dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT50_0[rel8->resource_block_coding];
        dlsch0_harq->rb_alloc[1] = localRIV2alloc_LUT50_1[rel8->resource_block_coding];
        dlsch0_harq->vrb_type = rel8->virtual_resource_block_assignment_flag;
        dlsch0_harq->nb_rb = RIV2nb_rb_LUT50[rel8->resource_block_coding];        //NPRB;
        break;
      case 100:
        if (fp->frame_type == TDD) {
  
  	dci_alloc->dci_length                         = sizeof_DCI1A_20MHz_TDD_1_6_t; 
          ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->type      = 1;
          ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->vrb_type  = rel8->virtual_resource_block_assignment_flag;
          ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->mcs       = rel8->mcs_1;
          ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->ndi       = rel8->new_data_indicator_1;
          ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
          ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->rv        = rel8->redundancy_version_1;
          ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->TPC       = rel8->tpc;
          ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->harq_pid  = rel8->harq_process;
          ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
          ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->padding   = 0;
          //        printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                         = sizeof_DCI1A_20MHz_FDD_t; 
  	((DCI1A_20MHz_FDD_t *)dci_pdu)->type          = 1;
          ((DCI1A_20MHz_FDD_t *)dci_pdu)->vrb_type      = rel8->virtual_resource_block_assignment_flag;
          ((DCI1A_20MHz_FDD_t *)dci_pdu)->mcs           = rel8->mcs_1;
          ((DCI1A_20MHz_FDD_t *)dci_pdu)->ndi           = rel8->new_data_indicator_1;
          ((DCI1A_20MHz_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
          ((DCI1A_20MHz_FDD_t *)dci_pdu)->rv            = rel8->redundancy_version_1;
          ((DCI1A_20MHz_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
          ((DCI1A_20MHz_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
          ((DCI1A_20MHz_FDD_t *)dci_pdu)->padding       = 0;
  	//      printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        }
        AssertFatal (rel8->virtual_resource_block_assignment_flag == LOCALIZED, "Distributed RB allocation not done yet\n");
        dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT100_0[rel8->resource_block_coding];
        dlsch0_harq->rb_alloc[1] = localRIV2alloc_LUT100_1[rel8->resource_block_coding];
        dlsch0_harq->rb_alloc[2] = localRIV2alloc_LUT100_2[rel8->resource_block_coding];
        dlsch0_harq->rb_alloc[3] = localRIV2alloc_LUT100_3[rel8->resource_block_coding];
        dlsch0_harq->vrb_type = rel8->virtual_resource_block_assignment_flag;
        dlsch0_harq->nb_rb = RIV2nb_rb_LUT100[rel8->resource_block_coding];       //NPRB;
        break;
      }
  
      if (rel8->rnti_type == 2) {
        // see 36-212 V8.6.0 p. 45
        NPRB = (rel8->tpc & 1) + 2;
        // 36-213 sec.7.1.7.2 p.26
  
        I_mcs     = rel8->mcs_1;
      }
      else {
        NPRB      = dlsch0_harq->nb_rb;
        I_mcs     = get_I_TBS(rel8->mcs_1);
      }
      AssertFatal(NPRB>0,"DCI 1A: NPRB = 0 (rnti %x, rnti type %d, tpc %d, round %d, resource_block_coding %d, harq process %d)\n",rel8->rnti,rel8->rnti_type,rel8->tpc,dlsch0_harq->round,rel8->resource_block_coding,rel8->harq_process);
      dlsch0_harq->rvidx         = rel8->redundancy_version_1;
      dlsch0_harq->Nl            = 1;
      dlsch0_harq->mimo_mode     = (fp->nb_antenna_ports_eNB == 1) ? SISO : ALAMOUTI;
      dlsch0_harq->dl_power_off  = 1;
      
      
  
      dlsch0_harq->mcs             = rel8->mcs_1;
      dlsch0_harq->Qm              = 2;
      dlsch0_harq->TBS             = TBStable[I_mcs][NPRB-1];
      dlsch0->harq_ids[frame%2][subframe]   = rel8->harq_process;
  #ifdef PHY_TX_THREAD
      dlsch0->active[subframe]     = 1;
  #else
      dlsch0->active               = 1;
  #endif
      dlsch0->rnti                 = rel8->rnti;
      //dlsch0->harq_ids[subframe]   = rel8->harq_process;
  
      if (dlsch0_harq->round == 0)
        dlsch0_harq->status = ACTIVE;
  
      dlsch0->harq_mask |= (1 << rel8->harq_process);
  
      if (rel8->rnti_type == 1) LOG_D(PHY,"DCI 1A: round %d, mcs %d, TBS %d, rballoc %x, rv %d, rnti %x, harq process %d\n",dlsch0_harq->round,rel8->mcs_1,dlsch0_harq->TBS,rel8->resource_block_coding,rel8->redundancy_version_1,rel8->rnti,rel8->harq_process);
  
      break;
    case NFAPI_DL_DCI_FORMAT_1:
  
      dci_alloc->format           = format1;
  #ifdef PHY_TX_THREAD
      dlsch0->active[subframe]    = 1;
  #else
      dlsch0->active              = 1;
  #endif
  
      LOG_D(PHY,"SFN/SF:%04d%d proc:TX:SFN/SF:%04d%d: Programming DLSCH for Format 1 DCI, harq_pid %d\n",frame,subframe,proc->frame_tx,subframe,rel8->harq_process);
  
      switch (fp->N_RB_DL) {
      case 6:
        if (fp->frame_type == TDD) {
  
  	dci_alloc->dci_length                     = sizeof_DCI1_1_5MHz_TDD_t; 
          ((DCI1_1_5MHz_TDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
          ((DCI1_1_5MHz_TDD_t *)dci_pdu)->mcs       = rel8->mcs_1;
          ((DCI1_1_5MHz_TDD_t *)dci_pdu)->ndi       = rel8->new_data_indicator_1;
          ((DCI1_1_5MHz_TDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
          ((DCI1_1_5MHz_TDD_t *)dci_pdu)->rv        = rel8->redundancy_version_1;
          ((DCI1_1_5MHz_TDD_t *)dci_pdu)->TPC       = rel8->tpc;
          ((DCI1_1_5MHz_TDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
          ((DCI1_1_5MHz_TDD_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
          ((DCI1_1_5MHz_TDD_t *)dci_pdu)->padding   = 0;
          //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                         = sizeof_DCI1_1_5MHz_FDD_t; 
          ((DCI1_1_5MHz_FDD_t *)dci_pdu)->rah           = rel8->resource_allocation_type;
          ((DCI1_1_5MHz_FDD_t *)dci_pdu)->mcs           = rel8->mcs_1;
          ((DCI1_1_5MHz_FDD_t *)dci_pdu)->ndi       = rel8->new_data_indicator_1;
          ((DCI1_1_5MHz_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
          ((DCI1_1_5MHz_FDD_t *)dci_pdu)->rv            = rel8->redundancy_version_1;
          ((DCI1_1_5MHz_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
          ((DCI1_1_5MHz_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
          ((DCI1_1_5MHz_FDD_t *)dci_pdu)->padding       = 0;
          //      printf("FDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        }
        break;
      case 25:
        if (fp->frame_type == TDD) {
  
  	dci_alloc->dci_length                      = sizeof_DCI1_5MHz_TDD_t; 
          ((DCI1_5MHz_TDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
          ((DCI1_5MHz_TDD_t *)dci_pdu)->mcs      = rel8->mcs_1;
          ((DCI1_5MHz_TDD_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
          ((DCI1_5MHz_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
          ((DCI1_5MHz_TDD_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
          ((DCI1_5MHz_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
          ((DCI1_5MHz_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
          ((DCI1_5MHz_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
          ((DCI1_5MHz_TDD_t *)dci_pdu)->padding  = 0;
          //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                  = sizeof_DCI1_5MHz_FDD_t; 
          ((DCI1_5MHz_FDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
          ((DCI1_5MHz_FDD_t *)dci_pdu)->mcs      = rel8->mcs_1;
          ((DCI1_5MHz_FDD_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
          ((DCI1_5MHz_FDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
          ((DCI1_5MHz_FDD_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
          ((DCI1_5MHz_FDD_t *)dci_pdu)->TPC      = rel8->tpc;
          ((DCI1_5MHz_FDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
          ((DCI1_5MHz_FDD_t *)dci_pdu)->padding  = 0;
          //      printf("FDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        }
        break;
      case 50:
        if (fp->frame_type == TDD) {
  
  	dci_alloc->dci_length                       = sizeof_DCI1_10MHz_TDD_t; 
          ((DCI1_10MHz_TDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
          ((DCI1_10MHz_TDD_t *)dci_pdu)->mcs      = rel8->mcs_1;
          ((DCI1_10MHz_TDD_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
          ((DCI1_10MHz_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
          ((DCI1_10MHz_TDD_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
          ((DCI1_10MHz_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
          ((DCI1_10MHz_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
          ((DCI1_10MHz_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
          ((DCI1_10MHz_TDD_t *)dci_pdu)->padding  = 0;
          //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                   = sizeof_DCI1_10MHz_FDD_t; 
          ((DCI1_10MHz_FDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
          ((DCI1_10MHz_FDD_t *)dci_pdu)->mcs      = rel8->mcs_1;
          ((DCI1_10MHz_FDD_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
          ((DCI1_10MHz_FDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
          ((DCI1_10MHz_FDD_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
          ((DCI1_10MHz_FDD_t *)dci_pdu)->TPC      = rel8->tpc;
          ((DCI1_10MHz_FDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
          ((DCI1_10MHz_FDD_t *)dci_pdu)->padding  = 0;
        }
        break;
      case 100:
        if (fp->frame_type == TDD) {
  
  	dci_alloc->dci_length                       = sizeof_DCI1_20MHz_TDD_t; 
          ((DCI1_20MHz_TDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
          ((DCI1_20MHz_TDD_t *)dci_pdu)->mcs      = rel8->mcs_1;
          ((DCI1_20MHz_TDD_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
          ((DCI1_20MHz_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
          ((DCI1_20MHz_TDD_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
          ((DCI1_20MHz_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
          ((DCI1_20MHz_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
          ((DCI1_20MHz_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
          ((DCI1_20MHz_TDD_t *)dci_pdu)->padding  = 0;
          //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                   = sizeof_DCI1_20MHz_FDD_t; 
          ((DCI1_20MHz_FDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
          ((DCI1_20MHz_FDD_t *)dci_pdu)->mcs      = rel8->mcs_1;
          ((DCI1_20MHz_FDD_t *)dci_pdu)->ndi      = rel8->new_data_indicator_1;
          ((DCI1_20MHz_FDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
          ((DCI1_20MHz_FDD_t *)dci_pdu)->rv       = rel8->redundancy_version_1;
          ((DCI1_20MHz_FDD_t *)dci_pdu)->TPC      = rel8->tpc;
          ((DCI1_20MHz_FDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
          ((DCI1_20MHz_FDD_t *)dci_pdu)->padding  = 0;
        }
        break;
      }
  
      AssertFatal (rel8->harq_process < 8, "Format 1: harq_pid=%d >= 8\n", rel8->harq_process);
  
  
      dlsch0_harq = dlsch0->harq_processes[rel8->harq_process];
      dlsch0_harq->codeword = 0;
  
      // printf("DCI: Setting subframe_tx for subframe %d\n",subframe);
      dlsch0->subframe_tx[subframe] = 1;
  
      conv_rballoc (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL, dlsch0_harq->rb_alloc);
  
      dlsch0_harq->nb_rb = conv_nprb (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL);
  
      NPRB = dlsch0_harq->nb_rb;
  
  
      AssertFatal (NPRB > 0, "NPRB == 0\n");
  
      dlsch0_harq->rvidx = rel8->redundancy_version_1;
  
      dlsch0_harq->Nl = 1;
      //    dlsch[0]->layer_index = 0;
      if (beamforming_mode == 0)
        dlsch0_harq->mimo_mode = (fp->nb_antenna_ports_eNB == 1) ? SISO : ALAMOUTI;
      else if (beamforming_mode == 7)
        dlsch0_harq->mimo_mode = TM7;
      else
        LOG_E (PHY, "Invalid beamforming mode %dL\n", beamforming_mode);
  
      dlsch0_harq->dl_power_off = 1;
  
  #ifdef PHY_TX_THREAD
      dlsch0->active[subframe] = 1;
  #else
      dlsch0->active = 1;
  #endif
  
  
  
      if (dlsch0_harq->round == 0) {
        dlsch0_harq->status = ACTIVE;
  
        //            printf("Setting DLSCH process %d to ACTIVE\n",rel8->harq_process);
        // MCS and TBS don't change across HARQ rounds
        dlsch0_harq->mcs = rel8->mcs_1;
        dlsch0_harq->Qm = get_Qm (rel8->mcs_1);
        dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][NPRB - 1];
  
      }
  
  
      LOG_D(PHY,"DCI: Set harq_ids[%d] to %d (%p)\n",subframe,rel8->harq_process,dlsch0);
      dlsch0->harq_ids[frame%2][subframe] = rel8->harq_process;
  
      dlsch0->harq_mask |= (1 << rel8->harq_process);
  
  
      dlsch0->rnti = rel8->rnti;
  
  
      break;
    case NFAPI_DL_DCI_FORMAT_2A:
  
      dci_alloc->format = format2A;
      switch (fp->N_RB_DL) {
      case 6:
        if (fp->frame_type == TDD) {
  	dci_alloc->dci_length                         = sizeof_DCI2A_1_5MHz_2A_TDD_t; 
          ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
          ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->mcs1     = rel8->mcs_1;
          ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->mcs2     = rel8->mcs_2;
          ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->ndi1     = rel8->new_data_indicator_1;
          ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->ndi2     = rel8->new_data_indicator_2;
          ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
          ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rv1      = rel8->redundancy_version_1;
          ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->rv2      = rel8->redundancy_version_2;
          ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
          ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
  	((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->tb_swap  = rel8->transport_block_to_codeword_swap_flag;
          ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
          /* there is no padding in this structure, it is exactly 32 bits */
          //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                         = sizeof_DCI2A_1_5MHz_2A_FDD_t; 
          ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rah          = rel8->resource_allocation_type;
          ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->mcs1         = rel8->mcs_1;
          ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->mcs2         = rel8->mcs_2;
          ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->ndi1         = rel8->new_data_indicator_1;
          ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->ndi2         = rel8->new_data_indicator_2;
          ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rballoc      = rel8->resource_block_coding;
          ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rv1          = rel8->redundancy_version_1;
          ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->rv2          = rel8->redundancy_version_2;
          ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->TPC          = rel8->tpc;
          ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->harq_pid     = rel8->harq_process;
  	((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->tb_swap      = rel8->transport_block_to_codeword_swap_flag;
  	((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->padding      = 0;
          //      printf("FDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        }
        break;
      case 25:
        if (fp->frame_type == TDD) {
  	dci_alloc->dci_length                        = sizeof_DCI2A_5MHz_2A_TDD_t; 
          ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
          ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->mcs1      = rel8->mcs_1;
          ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->mcs2      = rel8->mcs_2;
          ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->ndi1      = rel8->new_data_indicator_1;
          ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->ndi2      = rel8->new_data_indicator_2;
          ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
          ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rv1       = rel8->redundancy_version_1;
          ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->rv2       = rel8->redundancy_version_2;
          ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->TPC       = rel8->tpc;
          ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
  	((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->tb_swap   = rel8->transport_block_to_codeword_swap_flag;
          ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
          ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->padding   = 0;
          //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                           = sizeof_DCI2A_5MHz_2A_FDD_t; 
          ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rah           = rel8->resource_allocation_type;
          ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->mcs1          = rel8->mcs_1;
          ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->mcs2          = rel8->mcs_2;
          ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->ndi1          = rel8->new_data_indicator_1;
          ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->ndi2          = rel8->new_data_indicator_2;
          ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
          ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rv1           = rel8->redundancy_version_1;
          ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->rv2           = rel8->redundancy_version_2;
          ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
          ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
  	((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->tb_swap       = rel8->transport_block_to_codeword_swap_flag;	
  	((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->padding       = 0;
          //      printf("FDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        }
        break;
      case 50:
        if (fp->frame_type == TDD) {
  	dci_alloc->dci_length                        = sizeof_DCI2A_10MHz_2A_TDD_t; 
          ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
          ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->mcs1     = rel8->mcs_1;
          ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->mcs2     = rel8->mcs_2;
          ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->ndi1     = rel8->new_data_indicator_1;
          ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->ndi2     = rel8->new_data_indicator_2;
          ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
          ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rv1      = rel8->redundancy_version_1;
          ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->rv2      = rel8->redundancy_version_2;
          ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
          ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
  	((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->tb_swap  = rel8->transport_block_to_codeword_swap_flag;
          ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
          ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->padding  = 0;
          //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                        = sizeof_DCI2A_10MHz_2A_FDD_t; 
          ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
          ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->mcs1      = rel8->mcs_1;
          ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->mcs2      = rel8->mcs_2;
          ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->ndi1      = rel8->new_data_indicator_1;
          ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->ndi2      = rel8->new_data_indicator_2;
          ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
          ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rv1       = rel8->redundancy_version_1;
          ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->rv2       = rel8->redundancy_version_2;
          ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->TPC       = rel8->tpc;
          ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
  	((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->tb_swap   = rel8->transport_block_to_codeword_swap_flag;
  	((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->padding   = 0;
        }
        break;
      case 100:
        if (fp->frame_type == TDD) {
  	dci_alloc->dci_length                        = sizeof_DCI2A_20MHz_2A_TDD_t; 
          ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
          ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->mcs1      = rel8->mcs_1;
          ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->mcs2      = rel8->mcs_2;
          ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->ndi1      = rel8->new_data_indicator_1;
          ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->ndi2      = rel8->new_data_indicator_2;
          ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
          ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rv1       = rel8->redundancy_version_1;
          ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->rv2       = rel8->redundancy_version_2;
          ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->TPC       = rel8->tpc;
          ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
  	((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->tb_swap   = rel8->transport_block_to_codeword_swap_flag;
          ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
          ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->padding   = 0;
          //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                           = sizeof_DCI2A_20MHz_2A_FDD_t; 
          ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rah          = rel8->resource_allocation_type;
          ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->mcs1         = rel8->mcs_1;
          ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->mcs2         = rel8->mcs_2;
          ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->ndi1         = rel8->new_data_indicator_1;
          ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->ndi2         = rel8->new_data_indicator_2;
          ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rballoc      = rel8->resource_block_coding;
          ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rv1          = rel8->redundancy_version_1;
          ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->rv2          = rel8->redundancy_version_2;
          ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->TPC          = rel8->tpc;
          ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->harq_pid     = rel8->harq_process;
  	((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->tb_swap      = rel8->transport_block_to_codeword_swap_flag;
  	((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->padding      = 0;
        }
        break;
  
      }
  
      AssertFatal (rel8->harq_process < 8, "Format 2_2A: harq_pid=%d >= 8\n", rel8->harq_process);
  
  
      // Flip the TB to codeword mapping as described in 5.3.3.1.5 of 36-212 V11.3.0
      // note that we must set tbswap=0 in eNB scheduler if one TB is deactivated
  
      // This must be set as in TM4, does not work properly now.
      if (rel8->transport_block_to_codeword_swap_flag == 1) {
        dlsch0 = eNB->dlsch[UE_id][1];
        dlsch1 = eNB->dlsch[UE_id][0];
      }
  
      dlsch0_harq = dlsch0->harq_processes[rel8->harq_process];
      dlsch1_harq = dlsch1->harq_processes[rel8->harq_process];
  
      dlsch0->subframe_tx[subframe] = 1;
  
      dlsch0->harq_ids[frame%2][subframe] = rel8->harq_process;
      dlsch1->harq_ids[frame%2][subframe] = rel8->harq_process;
      //    printf("Setting DLSCH harq id %d to subframe %d\n",harq_pid,subframe);
  
  
      conv_rballoc (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL, dlsch0_harq->rb_alloc);
  
      dlsch1_harq->rb_alloc[0] = dlsch0_harq->rb_alloc[0];
      dlsch0_harq->nb_rb = conv_nprb (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL);
      dlsch1_harq->nb_rb = dlsch0_harq->nb_rb;
  
      AssertFatal (dlsch0_harq->nb_rb > 0, "nb_rb=0\n");
  
      dlsch0_harq->mcs = rel8->mcs_1;
      dlsch1_harq->mcs = rel8->mcs_2;
      dlsch0_harq->Qm = get_Qm (rel8->mcs_1);
      dlsch1_harq->Qm = get_Qm (rel8->mcs_2);
      dlsch0_harq->rvidx = rel8->redundancy_version_1;
      dlsch1_harq->rvidx = rel8->redundancy_version_2;
  
      // assume both TBs are active
      dlsch0_harq->Nl        = 1;
      dlsch1_harq->Nl        = 1;
  #ifdef PHY_TX_THREAD
      dlsch0->active[subframe] = 1;
      dlsch1->active[subframe] = 1;
  #else
      dlsch0->active = 1;
      dlsch1->active = 1;
  #endif
      dlsch0->harq_mask                         |= (1<<rel8->harq_process);
      dlsch1->harq_mask                         |= (1<<rel8->harq_process);
  
      // check if either TB is disabled (see 36-213 V11.3 Section )
      if ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0)) {
  #ifdef PHY_TX_THREAD
        dlsch0->active[subframe] = 0;
  #else
        dlsch0->active = 0;
  #endif
        dlsch0->harq_mask                         &= ~(1<<rel8->harq_process);
      }
  
      if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) {
  #ifdef PHY_TX_THREAD
        dlsch1->active[subframe]= 0;
  #else
        dlsch1->active = 0;
  #endif
        dlsch1->harq_mask                         &= ~(1<<rel8->harq_process);
      }
      // dlsch0_harq->dl_power_off = 0;
      // dlsch1_harq->dl_power_off = 0;
  
  
      if (fp->nb_antenna_ports_eNB == 2) {
        dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][dlsch0_harq->nb_rb - 1];
        dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][dlsch0_harq->nb_rb - 1];
  
  #ifdef PHY_TX_THREAD
        if ((dlsch0->active[subframe]==1) && (dlsch1->active[subframe]==1)) {
  #else
        if ((dlsch0->active==1) && (dlsch1->active==1)) {
  #endif
          dlsch0_harq->mimo_mode = LARGE_CDD;
          dlsch1_harq->mimo_mode = LARGE_CDD;
          dlsch0_harq->dl_power_off = 1;
          dlsch1_harq->dl_power_off = 1;
        } else {
          dlsch0_harq->mimo_mode = ALAMOUTI;
          dlsch1_harq->mimo_mode = ALAMOUTI;
        }
      } else if (fp->nb_antenna_ports_eNB == 4) { // 4 antenna case
  #ifdef PHY_TX_THREAD
        if ((dlsch0->active[subframe]==1) && (dlsch1->active[subframe]==1)) {
  #else
        if ((dlsch0->active==1) && (dlsch1->active==1)) {
  #endif
          switch (rel8->precoding_information) {
          case 0:                // one layer per transport block
            dlsch0_harq->mimo_mode = LARGE_CDD;
            dlsch1_harq->mimo_mode = LARGE_CDD;
            dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][dlsch0_harq->nb_rb - 1];
            dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][dlsch0_harq->nb_rb - 1];
            dlsch0_harq->dl_power_off = 1;
            dlsch1_harq->dl_power_off = 1;
            break;
  
          case 1:                // one-layers on TB 0, two on TB 1
            dlsch0_harq->mimo_mode = LARGE_CDD;
            dlsch1_harq->mimo_mode = LARGE_CDD;
            dlsch1_harq->Nl = 2;
            dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][(dlsch1_harq->nb_rb << 1) - 1];
            dlsch0_harq->dl_power_off = 1;
            dlsch1_harq->dl_power_off = 1;
            break;
  
          case 2:                // two-layers on TB 0, two on TB 1
            dlsch0_harq->mimo_mode = LARGE_CDD;
            dlsch1_harq->mimo_mode = LARGE_CDD;
            dlsch0_harq->Nl = 2;
            dlsch0_harq->dl_power_off = 1;
            dlsch1_harq->dl_power_off = 1;
  
            if (fp->N_RB_DL <= 56) {
              dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][(dlsch0_harq->nb_rb << 1) - 1];
              dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][(dlsch1_harq->nb_rb << 1) - 1];
            } else {
              LOG_E (PHY, "Add implementation of Table 7.1.7.2.2-1 for two-layer TBS conversion with N_RB_DL > 56\n");
            }
  
            break;
  
          case 3:                //
            LOG_E (PHY, "Illegal value (3) for TPMI in Format 2A DCI\n");
            break;
          }
  #ifdef PHY_TX_THREAD
        } else if (dlsch0->active[subframe] == 1) {
  #else
        } else if (dlsch0->active == 1) {
  #endif
          switch (rel8->precoding_information) {
          case 0:                // one layer per transport block
            dlsch0_harq->mimo_mode = ALAMOUTI;
            dlsch1_harq->mimo_mode = ALAMOUTI;
            dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][dlsch0_harq->nb_rb - 1];
            break;
  
          case 1:                // two-layers on TB 0
            dlsch0_harq->mimo_mode = LARGE_CDD;
            dlsch0_harq->Nl = 2;
            dlsch0_harq->dl_power_off = 1;
            dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][(dlsch0_harq->nb_rb << 1) - 1];
            break;
  
          case 2:                // two-layers on TB 0, two on TB 1
          case 3:                //
            LOG_E (PHY, "Illegal value %d for TPMI in Format 2A DCI with one transport block enabled\n", rel8->precoding_information);
            break;
          }
  #ifdef PHY_TX_THREAD
        } else if (dlsch1->active[subframe] == 1) {
  #else
        } else if (dlsch1->active == 1) {
  #endif
          switch (rel8->precoding_information) {
          case 0:                // one layer per transport block
            dlsch0_harq->mimo_mode = ALAMOUTI;
            dlsch1_harq->mimo_mode = ALAMOUTI;
            dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][dlsch1_harq->nb_rb - 1];
            break;
  
          case 1:                // two-layers on TB 0
            dlsch1_harq->mimo_mode = LARGE_CDD;
            dlsch1_harq->Nl = 2;
            dlsch1_harq->dl_power_off = 1;
            dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][(dlsch1_harq->nb_rb << 1) - 1];
            break;
  
          case 2:                // two-layers on TB 0, two on TB 1
          case 3:                //
            LOG_E (PHY, "Illegal value %d for TPMI in Format 2A DCI with one transport block enabled\n", rel8->precoding_information);
            break;
          }
        }
      } else {
        LOG_E (PHY, "Illegal number of antennas for eNB %d\n", fp->nb_antenna_ports_eNB);
      }
  
      // reset HARQ process if this is the first transmission
  #ifdef PHY_TX_THREAD
      if ((dlsch0->active[subframe]==1) && (dlsch0_harq->round == 0))
  #else
      if ((dlsch0->active==1) && (dlsch0_harq->round == 0))
  #endif
        dlsch0_harq->status = ACTIVE;
  
  #ifdef PHY_TX_THREAD
      if ((dlsch1->active[subframe]==1) && (dlsch1_harq->round == 0))
  #else
      if ((dlsch1->active==1) && (dlsch1_harq->round == 0))
  #endif
        dlsch1_harq->status = ACTIVE;
  
      dlsch0->rnti = rel8->rnti;
      dlsch1->rnti = rel8->rnti;
  
  
      break;
  
    case NFAPI_DL_DCI_FORMAT_2:
  
      dci_alloc->format = format2;
      switch (fp->N_RB_DL) {
      case 6:
        if (fp->frame_type == TDD) {
  	dci_alloc->dci_length                       = sizeof_DCI2_1_5MHz_2A_TDD_t; 
          ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->mcs1     = rel8->mcs_1;
          ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->mcs2     = rel8->mcs_2;
          ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->ndi1     = rel8->new_data_indicator_1;
          ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->ndi2     = rel8->new_data_indicator_2;
          ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
          ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->rv1      = rel8->redundancy_version_1;
          ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->rv2      = rel8->redundancy_version_2;
          ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
          ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
  	((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->tb_swap  = rel8->transport_block_to_codeword_swap_flag;
          ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;
          ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->tpmi     = rel8->precoding_information;
          ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->padding  = 0;
          //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                         = sizeof_DCI2_1_5MHz_2A_FDD_t; 
          ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->mcs1         = rel8->mcs_1;
          ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->mcs2         = rel8->mcs_2;
          ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->ndi1         = rel8->new_data_indicator_1;
          ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->ndi2         = rel8->new_data_indicator_2;
          ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->rballoc      = rel8->resource_block_coding;
          ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->rv1          = rel8->redundancy_version_1;
          ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->rv2          = rel8->redundancy_version_2;
          ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->TPC          = rel8->tpc;
          ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->harq_pid     = rel8->harq_process;
  	((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->tb_swap      = rel8->transport_block_to_codeword_swap_flag;
          ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->tpmi         = rel8->precoding_information;
          ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->padding      = 0;
          //      printf("FDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        }
        break;
      case 25:
        if (fp->frame_type == TDD) {
  	dci_alloc->dci_length                        = sizeof_DCI2_5MHz_2A_TDD_t; 
          ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
          ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs1      = rel8->mcs_1;
          ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs2      = rel8->mcs_2;
          ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->ndi1      = rel8->new_data_indicator_1;
          ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->ndi2      = rel8->new_data_indicator_2;
          ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
          ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rv1       = rel8->redundancy_version_1;
          ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->rv2       = rel8->redundancy_version_2;
          ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->TPC       = rel8->tpc;
          ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
  	((DCI2_5MHz_2A_TDD_t *)dci_pdu)->tb_swap   = rel8->transport_block_to_codeword_swap_flag;	
          ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;	
          ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->tpmi      = rel8->precoding_information;
          ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->padding   = 0;
          //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                           = sizeof_DCI2_5MHz_2A_FDD_t; 
          ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rah           = rel8->resource_allocation_type;
          ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->mcs1          = rel8->mcs_1;
          ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->mcs2          = rel8->mcs_2;
          ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->ndi1          = rel8->new_data_indicator_1;
          ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->ndi2          = rel8->new_data_indicator_2;
          ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rballoc       = rel8->resource_block_coding;
          ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rv1           = rel8->redundancy_version_1;
          ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->rv2           = rel8->redundancy_version_2;
          ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->TPC           = rel8->tpc;
          ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->harq_pid      = rel8->harq_process;
  	((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tb_swap       = rel8->transport_block_to_codeword_swap_flag;
          ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tpmi          = rel8->precoding_information;
          ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->padding       = 0;
          //      printf("FDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        }
        break;
      case 50:
        if (fp->frame_type == TDD) {
  	dci_alloc->dci_length                        = sizeof_DCI2_10MHz_2A_TDD_t; 
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rah      = rel8->resource_allocation_type;
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->mcs1     = rel8->mcs_1;
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->mcs2     = rel8->mcs_2;
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->ndi1     = rel8->new_data_indicator_1;
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->ndi2     = rel8->new_data_indicator_2;
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rballoc  = rel8->resource_block_coding;
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rv1      = rel8->redundancy_version_1;
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->rv2      = rel8->redundancy_version_2;
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->TPC      = rel8->tpc;
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->harq_pid = rel8->harq_process;
  	((DCI2_10MHz_2A_TDD_t *)dci_pdu)->tb_swap  = rel8->transport_block_to_codeword_swap_flag;	
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->dai      = rel8->downlink_assignment_index;	
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->tpmi     = rel8->precoding_information;
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->padding  = 0;
          //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                        = sizeof_DCI2_10MHz_2A_FDD_t; 
          ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
          ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->mcs1      = rel8->mcs_1;
          ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->mcs2      = rel8->mcs_2;
          ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->ndi1      = rel8->new_data_indicator_1;
          ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->ndi2      = rel8->new_data_indicator_2;
          ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
          ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rv1       = rel8->redundancy_version_1;
          ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->rv2       = rel8->redundancy_version_2;
          ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->TPC       = rel8->tpc;
          ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
  	((DCI2_10MHz_2A_FDD_t *)dci_pdu)->tb_swap   = rel8->transport_block_to_codeword_swap_flag;
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->tpmi      = rel8->precoding_information;
          ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->padding   = 0;
        }
        break;
      case 100:
        if (fp->frame_type == TDD) {
  	dci_alloc->dci_length                        = sizeof_DCI2_20MHz_2A_TDD_t;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rah       = rel8->resource_allocation_type;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->mcs1      = rel8->mcs_1;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->mcs2      = rel8->mcs_2;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->ndi1      = rel8->new_data_indicator_1;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->ndi2      = rel8->new_data_indicator_2;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rballoc   = rel8->resource_block_coding;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rv1       = rel8->redundancy_version_1;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->rv2       = rel8->redundancy_version_2;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->TPC       = rel8->tpc;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->harq_pid  = rel8->harq_process;
  	((DCI2_20MHz_2A_TDD_t *)dci_pdu)->tb_swap   = rel8->transport_block_to_codeword_swap_flag;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->dai       = rel8->downlink_assignment_index;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->tpmi      = rel8->precoding_information;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->padding   = 0;
          //        printf("TDD 1: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB);
        } else {
  	dci_alloc->dci_length                           = sizeof_DCI2_20MHz_2A_FDD_t;
          ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rah          = rel8->resource_allocation_type;
          ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->mcs1         = rel8->mcs_1;
          ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->mcs2         = rel8->mcs_2;
          ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->ndi1         = rel8->new_data_indicator_1;
          ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->ndi2         = rel8->new_data_indicator_2;
          ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rballoc      = rel8->resource_block_coding;
          ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rv1          = rel8->redundancy_version_1;
          ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->rv2          = rel8->redundancy_version_2;
          ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->TPC          = rel8->tpc;
          ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->harq_pid     = rel8->harq_process;
  	((DCI2_20MHz_2A_FDD_t *)dci_pdu)->tb_swap      = rel8->transport_block_to_codeword_swap_flag;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->tpmi         = rel8->precoding_information;
          ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->padding      = 0;
        }
        break;
  
      }
  
      AssertFatal (rel8->harq_process >= 8, "Format 2_2A: harq_pid=%d >= 8\n", rel8->harq_process);
  
  
      // Flip the TB to codeword mapping as described in 5.3.3.1.5 of 36-212 V11.3.0
      // note that we must set tbswap=0 in eNB scheduler if one TB is deactivated
      TB0_active = 1;
      TB1_active = 1;
  
      if ((rel8->redundancy_version_1 == 1) && (rel8->mcs_1 == 0)) {
        TB0_active = 0;
      }
      if ((rel8->redundancy_version_2 == 1) && (rel8->mcs_2 == 0)) {
        TB1_active = 0;
      }
  #ifdef DEBUG_HARQ
      printf ("RV0 = %d, RV1 = %d. MCS0 = %d, MCS1=%d\n", rel8->redundancy_version_1, rel8->redundancy_version_2, rel8->mcs_1, rel8->mcs_2);
  #endif
      if (TB0_active && TB1_active && rel8->transport_block_to_codeword_swap_flag==0) {
  #ifdef PHY_TX_THREAD
        dlsch0->active[subframe] = 1;
        dlsch1->active[subframe] = 1;
  #else
        dlsch0->active = 1;
        dlsch1->active = 1;
  #endif
        dlsch0->harq_mask                         |= (1<<rel8->harq_process);
        dlsch1->harq_mask                         |= (1<<rel8->harq_process);
        dlsch0_harq = dlsch0->harq_processes[rel8->harq_process];
        dlsch1_harq = dlsch1->harq_processes[rel8->harq_process];
        dlsch0_harq->mcs = rel8->mcs_1;
        dlsch1_harq->mcs = rel8->mcs_2;
        dlsch0_harq->Qm = get_Qm (rel8->mcs_1);
        dlsch1_harq->Qm = get_Qm (rel8->mcs_2);
        dlsch0_harq->rvidx = rel8->redundancy_version_1;
        dlsch1_harq->rvidx = rel8->redundancy_version_2;
        dlsch0_harq->status = ACTIVE;
        dlsch1_harq->status = ACTIVE;
        dlsch0_harq->codeword = 0;
        dlsch1_harq->codeword = 1;
  #ifdef DEBUG_HARQ
        printf ("\n ENB: BOTH ACTIVE\n");
  #endif
      } else if (TB0_active && TB1_active && rel8->transport_block_to_codeword_swap_flag == 1) {
        dlsch0 = eNB->dlsch[UE_id][1];
        dlsch1 = eNB->dlsch[UE_id][0];
  #ifdef PHY_TX_THREAD
        dlsch0->active[subframe] = 1;
        dlsch1->active[subframe] = 1;
  #else
        dlsch0->active = 1;
        dlsch1->active = 1;
  #endif
  
        dlsch0->harq_mask |= (1 << rel8->harq_process);
        dlsch1->harq_mask |= (1 << rel8->harq_process);
  
        dlsch1_harq = dlsch1->harq_processes[rel8->harq_process];
        dlsch0_harq->mcs = rel8->mcs_1;
        dlsch1_harq->mcs = rel8->mcs_2;
        dlsch0_harq->Qm = get_Qm (rel8->mcs_1);
        dlsch1_harq->Qm = get_Qm (rel8->mcs_2);
        dlsch0_harq->rvidx = rel8->redundancy_version_1;
        dlsch1_harq->rvidx = rel8->redundancy_version_2;
        dlsch0_harq->status = ACTIVE;
        dlsch1_harq->status = ACTIVE;
        dlsch0_harq->codeword=1;
        dlsch1_harq->codeword=0;
      }
      else if (TB0_active && (TB1_active==0)) {
  #ifdef PHY_TX_THREAD
        dlsch0->active[subframe] = 1;
  #else
        dlsch0->active = 1;
  #endif
        dlsch0->harq_mask                         |= (1<<rel8->harq_process);
        dlsch0_harq = dlsch0->harq_processes[rel8->harq_process];
        dlsch0_harq->mcs = rel8->mcs_1;
        dlsch0_harq->Qm = get_Qm (rel8->mcs_1);
        dlsch0_harq->rvidx = rel8->redundancy_version_1;
        dlsch0_harq->status = ACTIVE;
        dlsch0_harq->codeword = 0;
        dlsch1 = NULL;
        dlsch1_harq = NULL;
  #ifdef DEBUG_HARQ
        printf ("\n ENB: TB1 is deactivated, retransmit TB0 transmit in TM6\n");
  #endif
      }
      else if ((TB0_active==0) && TB1_active) {
  #ifdef PHY_TX_THREAD
        dlsch1->active[subframe] = 1;
  #else
        dlsch1->active = 1;
  #endif
        dlsch1->harq_mask                         |= (1<<rel8->harq_process);
        dlsch1_harq = dlsch1->harq_processes[rel8->harq_process];
        dlsch1_harq->mcs = rel8->mcs_2;
        dlsch1_harq->Qm = get_Qm (rel8->mcs_2);
        dlsch1_harq->rvidx = rel8->redundancy_version_2;
        dlsch1_harq->status = ACTIVE;
        dlsch1_harq->codeword = 0;
        dlsch0 = NULL;
        dlsch0_harq = NULL;
  #ifdef DEBUG_HARQ
        printf ("\n ENB: TB0 is deactivated, retransmit TB1 transmit in TM6\n");
  #endif
      }
  
      if (dlsch0 != NULL) {
        dlsch0->subframe_tx[subframe] = 1;
  
        dlsch0->harq_ids[frame%2][subframe] = rel8->harq_process;
      }
  
      if (dlsch1_harq != NULL){
        dlsch1->harq_ids[frame%2][subframe] = rel8->harq_process;
      }
  
  
      if (dlsch0 != NULL) {
        conv_rballoc (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL, dlsch0_harq->rb_alloc);
  
        dlsch0_harq->nb_rb = conv_nprb (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL);
  
        if (dlsch1 != NULL) {
          dlsch1_harq->rb_alloc[0] = dlsch0_harq->rb_alloc[0];
          dlsch1_harq->nb_rb = dlsch0_harq->nb_rb;
        }
      } else if ((dlsch0 == NULL) && (dlsch1 != NULL)) {
        conv_rballoc (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL, dlsch1_harq->rb_alloc);
  
        dlsch1_harq->nb_rb = conv_nprb (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL);
      }
  
      // assume both TBs are active
      if (dlsch0_harq != NULL)
        dlsch0_harq->Nl = 1;
      if (dlsch1_harq != NULL)
        dlsch1_harq->Nl = 1;
  
  
      // check if either TB is disabled (see 36-213 V11.3 Section )
  
      if (fp->nb_antenna_ports_eNB == 2) {
        if ((dlsch0 != NULL) && (dlsch1 != NULL)) {       //two CW active
  
          dlsch0_harq->dl_power_off = 1;
          dlsch1_harq->dl_power_off = 1;
          dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][dlsch0_harq->nb_rb - 1];
          dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][dlsch1_harq->nb_rb - 1];
          switch (rel8->precoding_information) {
          case 0:
            dlsch0_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODING1;
            dlsch1_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODING1;
            dlsch0_harq->pmi_alloc = pmi_extend (fp, 0, 1);
            dlsch1_harq->pmi_alloc = pmi_extend (fp, 0, 1);
            break;
          case 1:
            dlsch0_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODINGj;
            dlsch1_harq->mimo_mode = DUALSTREAM_UNIFORM_PRECODINGj;
            dlsch0_harq->pmi_alloc = pmi_extend (fp, 1, 1);
            dlsch0_harq->pmi_alloc = pmi_extend (fp, 1, 1);
  
            break;
          case 2:                // PUSCH precoding
            dlsch0_harq->mimo_mode = DUALSTREAM_PUSCH_PRECODING;
            dlsch0_harq->pmi_alloc = DL_pmi_single;
            dlsch1_harq->mimo_mode = DUALSTREAM_PUSCH_PRECODING;
            dlsch1_harq->pmi_alloc = DL_pmi_single;
            break;
          default:
            break;
          }
        } else if ((dlsch0 != NULL) && (dlsch1 == NULL)) {        // only CW 0 active
          dlsch0_harq->dl_power_off = 1;
          dlsch0_harq->TBS = TBStable[get_I_TBS (dlsch0_harq->mcs)][dlsch0_harq->nb_rb - 1];
          switch (rel8->precoding_information) {
          case 0:
            dlsch0_harq->mimo_mode = ALAMOUTI;
            break;
          case 1:
            dlsch0_harq->mimo_mode = UNIFORM_PRECODING11;
            dlsch0_harq->pmi_alloc = pmi_extend (fp, 0, 0);
            break;
          case 2:
            dlsch0_harq->mimo_mode = UNIFORM_PRECODING1m1;
            dlsch0_harq->pmi_alloc = pmi_extend (fp, 1, 0);
            break;
          case 3:
            dlsch0_harq->mimo_mode = UNIFORM_PRECODING1j;
            dlsch0_harq->pmi_alloc = pmi_extend (fp, 2, 0);
            break;
          case 4:
            dlsch0_harq->mimo_mode = UNIFORM_PRECODING1mj;
            dlsch0_harq->pmi_alloc = pmi_extend (fp, 3, 0);
            break;
          case 5:
            dlsch0_harq->mimo_mode = PUSCH_PRECODING0;
            dlsch0_harq->pmi_alloc = DL_pmi_single;
            break;
          case 6:
            dlsch0_harq->mimo_mode = PUSCH_PRECODING1;
            dlsch0_harq->pmi_alloc = DL_pmi_single;
            break;
          }
        } else if ((dlsch0 == NULL) && (dlsch1 != NULL)) {
          dlsch1_harq->dl_power_off = 1;
          dlsch1_harq->TBS = TBStable[get_I_TBS (dlsch1_harq->mcs)][dlsch1_harq->nb_rb - 1];
          switch (rel8->precoding_information) {
          case 0:
            dlsch1_harq->mimo_mode = ALAMOUTI;
            break;
          case 1:
            dlsch1_harq->mimo_mode = UNIFORM_PRECODING11;
            dlsch1_harq->pmi_alloc = pmi_extend (fp, 0, 0);
            break;
          case 2:
            dlsch1_harq->mimo_mode = UNIFORM_PRECODING1m1;
            dlsch1_harq->pmi_alloc = pmi_extend (fp, 1, 0);
            break;
          case 3:
            dlsch1_harq->mimo_mode = UNIFORM_PRECODING1j;
            dlsch1_harq->pmi_alloc = pmi_extend (fp, 2, 0);
            break;
          case 4:
            dlsch1_harq->mimo_mode = UNIFORM_PRECODING1mj;
            dlsch1_harq->pmi_alloc = pmi_extend (fp, 3, 0);
            break;
          case 5:
            dlsch1_harq->mimo_mode = PUSCH_PRECODING0;
            dlsch1_harq->pmi_alloc = DL_pmi_single;
            break;
          case 6:
            dlsch1_harq->mimo_mode = PUSCH_PRECODING1;
            dlsch1_harq->pmi_alloc = DL_pmi_single;
            break;
          }
        }
  
      } else if (fp->nb_antenna_ports_eNB == 4) {
        // fill in later
      }
      // reset HARQ process if this is the first transmission
      /* if (dlsch0_harq->round == 0)
         dlsch0_harq->status = ACTIVE;
  
         if (dlsch1_harq->round == 0)
         dlsch1_harq->status = ACTIVE; */
      if (dlsch0_harq != NULL)
        dlsch0->rnti = rel8->rnti;
      if (dlsch1 != NULL)
        dlsch1->rnti = rel8->rnti;
  
      break;
    }
  
    if (dlsch0_harq) {
      dlsch0_harq->frame    = frame;
      dlsch0_harq->subframe = subframe;
    }
    if (dlsch1_harq) {
      dlsch1_harq->frame    = frame;
      dlsch1_harq->subframe = subframe;
    }
  #ifdef DEBUG_DCI
  
    if (dlsch0) {
      printf ("dlsch0 eNB: dlsch0   %p\n", dlsch0);
      printf ("dlsch0 eNB: rnti     %x\n", dlsch0->rnti);
      printf ("dlsch0 eNB: NBRB     %d\n", dlsch0_harq->nb_rb);
      printf ("dlsch0 eNB: rballoc  %x\n", dlsch0_harq->rb_alloc[0]);
      printf ("dlsch0 eNB: harq_pid %d\n", harq_pid);
      printf ("dlsch0 eNB: round    %d\n", dlsch0_harq->round);
      printf ("dlsch0 eNB: rvidx    %d\n", dlsch0_harq->rvidx);
      printf ("dlsch0 eNB: TBS      %d (NPRB %d)\n", dlsch0_harq->TBS, NPRB);
      printf ("dlsch0 eNB: mcs      %d\n", dlsch0_harq->mcs);
      printf ("dlsch0 eNB: tpmi %d\n", rel8->precoding_information);
      printf ("dlsch0 eNB: mimo_mode %d\n", dlsch0_harq->mimo_mode);
    }
  
    if (dlsch1) {
      printf ("dlsch1 eNB: dlsch1   %p\n", dlsch1);
      printf ("dlsch1 eNB: rnti     %x\n", dlsch1->rnti);
      printf ("dlsch1 eNB: NBRB     %d\n", dlsch1_harq->nb_rb);
      printf ("dlsch1 eNB: rballoc  %x\n", dlsch1_harq->rb_alloc[0]);
      printf ("dlsch1 eNB: harq_pid %d\n", harq_pid);
      printf ("dlsch1 eNB: round    %d\n", dlsch1_harq->round);
      printf ("dlsch1 eNB: rvidx    %d\n", dlsch1_harq->rvidx);
      printf ("dlsch1 eNB: TBS      %d (NPRB %d)\n", dlsch1_harq->TBS, NPRB);
      printf ("dlsch1 eNB: mcs      %d\n", dlsch1_harq->mcs);
      printf ("dlsch1 eNB: tpmi %d\n", rel8->precoding_information);
      printf ("dlsch1 eNB: mimo_mode %d\n", dlsch1_harq->mimo_mode);
    }
  #endif
  //printf("DCI %d.%d rnti %d harq %d TBS %d\n", frame, subframe, rel8->rnti, rel8->harq_process, dlsch0_harq->TBS);
  #if T_TRACER
    if (dlsch0->active)
      T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(0), T_INT(frame), T_INT(subframe),
        T_INT(rel8->rnti), T_INT(rel8->dci_format), T_INT(rel8->harq_process),
        T_INT(rel8->mcs_1), T_INT(dlsch0_harq->TBS));
  #endif
  
  }
  
  
  void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,mDCI_ALLOC_t *dci_alloc,nfapi_dl_config_mpdcch_pdu *pdu){
  
    LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  
    uint8_t        *dci_pdu = &dci_alloc->dci_pdu[0];
    nfapi_dl_config_mpdcch_pdu_rel13_t *rel13 = &pdu->mpdcch_pdu_rel13;
  
  
    LTE_eNB_DLSCH_t *dlsch0 = NULL;
    LTE_DL_eNB_HARQ_t *dlsch0_harq = NULL;
    int             UE_id;
    int             subframe = proc->subframe_tx;
    int             frame = proc->frame_tx;
  
    dci_alloc->firstCCE = rel13->ecce_index;
    dci_alloc->L = rel13->aggregation_level;
    dci_alloc->rnti = rel13->rnti;
    dci_alloc->harq_pid = rel13->harq_process;
    dci_alloc->narrowband = rel13->mpdcch_narrow_band;
    dci_alloc->number_of_prb_pairs = rel13->number_of_prb_pairs;
    dci_alloc->resource_block_assignment = rel13->resource_block_assignment;
    dci_alloc->transmission_type = rel13->mpdcch_tansmission_type;
    dci_alloc->start_symbol = rel13->start_symbol;
    dci_alloc->ce_mode = rel13->ce_mode;
    dci_alloc->dmrs_scrambling_init = rel13->drms_scrambling_init;
    dci_alloc->i0 = rel13->initial_transmission_sf_io;
  
  
    UE_id = find_dlsch (rel13->rnti, eNB, SEARCH_EXIST_OR_FREE);
    AssertFatal (UE_id != -1, "no free or exiting dlsch_context\n");
    AssertFatal (UE_id < NUMBER_OF_UE_MAX, "returned UE_id %d >= %d(NUMBER_OF_UE_MAX)\n", UE_id, NUMBER_OF_UE_MAX);
    dlsch0 = eNB->dlsch[UE_id][0];
    dlsch0_harq = dlsch0->harq_processes[rel13->harq_process];
  
    dci_alloc->ra_flag = 0;
  
    if (rel13->rnti_type == 2) {
      dci_alloc->ra_flag = 1;
    }
  
    AssertFatal (fp->frame_type == FDD, "TDD is not supported yet for eMTC\n");
    AssertFatal (fp->N_RB_DL == 25 || fp->N_RB_DL == 50 || fp->N_RB_DL == 100, "eMTC only with N_RB_DL = 25,50,100\n");
  
    switch (rel13->dci_format) {
  
  
    case 10:                     // Format 6-1A
      dci_alloc->format = format6_1A;
      switch (fp->N_RB_DL) {
  
      case 25:
        dci_alloc->dci_length = sizeof_DCI6_1A_5MHz_t;
        ((DCI6_1A_5MHz_t *) dci_pdu)->type = 1;
        ((DCI6_1A_5MHz_t *) dci_pdu)->hopping = rel13->frequency_hopping_enabled_flag;
        ((DCI6_1A_5MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
        ((DCI6_1A_5MHz_t *) dci_pdu)->mcs = rel13->mcs;
        ((DCI6_1A_5MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
        ((DCI6_1A_5MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
        ((DCI6_1A_5MHz_t *) dci_pdu)->ndi = rel13->new_data_indicator;
        ((DCI6_1A_5MHz_t *) dci_pdu)->rv = rel13->redundancy_version;
        ((DCI6_1A_5MHz_t *) dci_pdu)->TPC = rel13->tpc;
        ((DCI6_1A_5MHz_t *) dci_pdu)->srs_req = rel13->srs_request;
        ((DCI6_1A_5MHz_t *) dci_pdu)->harq_ack_off = rel13->harq_resource_offset;
        ((DCI6_1A_5MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
  
        break;
      case 50:
        dci_alloc->dci_length = sizeof_DCI6_1A_10MHz_t;
        ((DCI6_1A_10MHz_t *) dci_pdu)->type = 1;
        ((DCI6_1A_10MHz_t *) dci_pdu)->hopping = rel13->frequency_hopping_enabled_flag;
        ((DCI6_1A_10MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding&31;
        ((DCI6_1A_10MHz_t *) dci_pdu)->narrowband = rel13->resource_block_coding>>5;
        ((DCI6_1A_10MHz_t *) dci_pdu)->mcs = rel13->mcs;
        ((DCI6_1A_10MHz_t *) dci_pdu)->rep = (rel13->pdsch_reptition_levels);
        ((DCI6_1A_10MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
        ((DCI6_1A_10MHz_t *) dci_pdu)->ndi = rel13->new_data_indicator;
        ((DCI6_1A_10MHz_t *) dci_pdu)->rv = rel13->redundancy_version;
        ((DCI6_1A_10MHz_t *) dci_pdu)->TPC = rel13->tpc;
        ((DCI6_1A_10MHz_t *) dci_pdu)->srs_req = rel13->srs_request;
        ((DCI6_1A_10MHz_t *) dci_pdu)->harq_ack_off = rel13->harq_resource_offset;
        ((DCI6_1A_10MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
  
        LOG_D(PHY,"Frame %d, Subframe %d : Programming Format 6-1A DCI, type %d, hopping %d, narrowband %d, rballoc %x, mcs %d, rep %d, harq_pid %d, ndi %d, rv %d, TPC %d, srs_req %d, harq_ack_off %d, dci_rep r%d => %x\n",
  	    frame,subframe,
  	    ((DCI6_1A_10MHz_t *) dci_pdu)->type,
  	    ((DCI6_1A_10MHz_t *) dci_pdu)->hopping,
  	    ((DCI6_1A_10MHz_t *) dci_pdu)->narrowband,
  	    ((DCI6_1A_10MHz_t *) dci_pdu)->rballoc,
  	    ((DCI6_1A_10MHz_t *) dci_pdu)->mcs,
  	    ((DCI6_1A_10MHz_t *) dci_pdu)->rep,
  	    ((DCI6_1A_10MHz_t *) dci_pdu)->harq_pid,
  	    ((DCI6_1A_10MHz_t *) dci_pdu)->ndi,
  	    ((DCI6_1A_10MHz_t *) dci_pdu)->rv,
  	    ((DCI6_1A_10MHz_t *) dci_pdu)->TPC,
  	    ((DCI6_1A_10MHz_t *) dci_pdu)->srs_req,
  	    ((DCI6_1A_10MHz_t *) dci_pdu)->harq_ack_off,
  	    ((DCI6_1A_10MHz_t *) dci_pdu)->dci_rep,
  	    ((uint32_t*)dci_pdu)[0]);
        break;
      case 100:
        dci_alloc->dci_length = sizeof_DCI6_1A_20MHz_t;
        ((DCI6_1A_20MHz_t *) dci_pdu)->type = 1;
        ((DCI6_1A_20MHz_t *) dci_pdu)->hopping = rel13->frequency_hopping_enabled_flag;
        ((DCI6_1A_20MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
        ((DCI6_1A_20MHz_t *) dci_pdu)->mcs = rel13->mcs;
        ((DCI6_1A_20MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
        ((DCI6_1A_20MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
        ((DCI6_1A_20MHz_t *) dci_pdu)->ndi = rel13->new_data_indicator;
        ((DCI6_1A_20MHz_t *) dci_pdu)->rv = rel13->redundancy_version;
        ((DCI6_1A_20MHz_t *) dci_pdu)->TPC = rel13->tpc;
        ((DCI6_1A_20MHz_t *) dci_pdu)->srs_req = rel13->srs_request;
        ((DCI6_1A_20MHz_t *) dci_pdu)->harq_ack_off = rel13->harq_resource_offset;
        ((DCI6_1A_20MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
        break;
      }
      break;
    case 11:                     // Format 6-1B
      dci_alloc->format = format6_1B;
      switch (fp->N_RB_DL) {
  
      case 25:
        dci_alloc->dci_length = sizeof_DCI6_1B_5MHz_t;
        ((DCI6_1B_5MHz_t *) dci_pdu)->type = 1;
        ((DCI6_1B_5MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
        ((DCI6_1B_5MHz_t *) dci_pdu)->mcs = rel13->mcs;
        ((DCI6_1B_5MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
        ((DCI6_1B_5MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
        ((DCI6_1B_5MHz_t *) dci_pdu)->ndi = rel13->new_data_indicator;
        ((DCI6_1B_5MHz_t *) dci_pdu)->harq_ack_off = rel13->harq_resource_offset;
        ((DCI6_1B_5MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
  
        break;
      case 50:
        dci_alloc->dci_length = sizeof_DCI6_1B_10MHz_t;
        ((DCI6_1B_10MHz_t *) dci_pdu)->type = 1;
        ((DCI6_1B_10MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
        ((DCI6_1B_10MHz_t *) dci_pdu)->mcs = rel13->mcs;
        ((DCI6_1B_10MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
        ((DCI6_1B_10MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
        ((DCI6_1B_10MHz_t *) dci_pdu)->ndi = rel13->new_data_indicator;
        ((DCI6_1B_10MHz_t *) dci_pdu)->harq_ack_off = rel13->harq_resource_offset;
        ((DCI6_1B_10MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
        break;
      case 100:
        dci_alloc->dci_length = sizeof_DCI6_1B_20MHz_t;
        ((DCI6_1B_20MHz_t *) dci_pdu)->type = 1;
        ((DCI6_1B_20MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
        ((DCI6_1B_20MHz_t *) dci_pdu)->mcs = rel13->mcs;
        ((DCI6_1B_20MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
        ((DCI6_1B_20MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
        ((DCI6_1B_20MHz_t *) dci_pdu)->ndi = rel13->new_data_indicator;
        ((DCI6_1B_20MHz_t *) dci_pdu)->harq_ack_off = rel13->harq_resource_offset;
        ((DCI6_1B_20MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
        break;
      }
    case 12:                     // Format 6-2
      dci_alloc->format = format6_2;
      switch (fp->N_RB_DL) {
      case 25:
        dci_alloc->dci_length = sizeof_DCI6_2_5MHz_t;
        if (rel13->paging_direct_indication_differentiation_flag == 0) {
          ((DCI6_2_di_5MHz_t *) dci_pdu)->type = 0;
          ((DCI6_2_di_5MHz_t *) dci_pdu)->di_info = rel13->direct_indication;
        } else {
          ((DCI6_2_paging_5MHz_t *) dci_pdu)->type = 1;
          ((DCI6_2_paging_5MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
          ((DCI6_2_paging_5MHz_t *) dci_pdu)->mcs = rel13->mcs;
          ((DCI6_2_paging_5MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
          ((DCI6_2_paging_5MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
        }
  
        break;
      case 50:
  
        dci_alloc->dci_length = sizeof_DCI6_2_10MHz_t;
        if (rel13->paging_direct_indication_differentiation_flag == 0) {
          ((DCI6_2_di_10MHz_t *) dci_pdu)->type = 0;
          ((DCI6_2_di_10MHz_t *) dci_pdu)->di_info = rel13->direct_indication;
        } else {
          ((DCI6_2_paging_10MHz_t *) dci_pdu)->type = 1;
          ((DCI6_2_paging_10MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
          ((DCI6_2_paging_10MHz_t *) dci_pdu)->mcs = rel13->mcs;
          ((DCI6_2_paging_10MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
          ((DCI6_2_paging_10MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
        }
  
        break;
      case 100:
        dci_alloc->dci_length = sizeof_DCI6_2_20MHz_t;
        if (rel13->paging_direct_indication_differentiation_flag == 0) {
          ((DCI6_2_di_20MHz_t *) dci_pdu)->type = 0;
          ((DCI6_2_di_20MHz_t *) dci_pdu)->di_info = rel13->direct_indication;
        } else {
          ((DCI6_2_paging_20MHz_t *) dci_pdu)->type = 1;
          ((DCI6_2_paging_20MHz_t *) dci_pdu)->rballoc = rel13->resource_block_coding;
          ((DCI6_2_paging_20MHz_t *) dci_pdu)->mcs = rel13->mcs;
          ((DCI6_2_paging_20MHz_t *) dci_pdu)->rep = rel13->pdsch_reptition_levels;
          ((DCI6_2_paging_20MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
        }
  
        break;
      }
    }
    AssertFatal (rel13->harq_process < 8, "ERROR: Format 6_1A: harq_pid=%d >= 8\n", rel13->harq_process);
  
    dlsch0->ue_type = rel13->ce_mode;
  
    dlsch0_harq = dlsch0->harq_processes[rel13->harq_process];
    dlsch0_harq->codeword = 0;
  
    // printf("DCI: Setting subframe_tx for subframe %d\n",subframe);
    dlsch0->subframe_tx[(subframe + 2) % 10] = 1;
    LOG_D(PHY,"PDSCH : resource_block_coding %x\n",rel13->resource_block_coding);
  
    conv_eMTC_rballoc (rel13->resource_block_coding,
  		     fp->N_RB_DL,
  		     dlsch0_harq->rb_alloc);
  
    dlsch0_harq->nb_rb = RIV2nb_rb_LUT6[rel13->resource_block_coding & 31];       // this is the 6PRB RIV
  
  
    dlsch0_harq->rvidx = rel13->redundancy_version;
  
    dlsch0_harq->Nl = 1;
    //    dlsch[0]->layer_index = 0;
    //  if (beamforming_mode == 0)
    dlsch0_harq->mimo_mode = (fp->nb_antenna_ports_eNB == 1) ? SISO : ALAMOUTI;
    //else if (beamforming_mode == 7)
    //  dlsch0_harq->mimo_mode = TM7;
    //else
    //LOG_E(PHY,"Invalid beamforming mode %dL\n", beamforming_mode);
  
    dlsch0_harq->dl_power_off = 1;
  
    dlsch0->subframe_tx[subframe] = 1;
    if (dlsch0->rnti != rel13->rnti) {     // if rnti of dlsch is not the same as in the config, this is a new entry
      dlsch0_harq->round = 0;
      dlsch0->harq_mask =0;
      printf("*********************** rnti %x => %x, pos %d\n",rel13->rnti,dlsch0->rnti,UE_id);
    }
    if ((dlsch0->harq_mask & (1 << rel13->harq_process)) > 0) {
      if ((rel13->new_data_indicator != dlsch0_harq->ndi)||(dci_alloc->ra_flag==1))
        dlsch0_harq->round = 0;
    } else {                      // process is inactive, so activate and set round to 0
      dlsch0_harq->round = 0;
    }
    dlsch0_harq->ndi = rel13->new_data_indicator;
  
    if (dlsch0_harq->round == 0) {
      dlsch0_harq->status = ACTIVE;
      dlsch0_harq->mcs = rel13->mcs;
      if (dci_alloc->ra_flag == 0) // get TBS from table using mcs and nb_rb
        dlsch0_harq->TBS         = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1];
      else if (rel13->tpc == 0)  //N1A_PRB=2, get TBS from table using mcs and nb_rb=2
        dlsch0_harq->TBS         = TBStable[get_I_TBS(dlsch0_harq->mcs)][1];
      else if (rel13->tpc == 1)  //N1A_PRB=3, get TBS from table using mcs and nb_rb=3
        dlsch0_harq->TBS         = TBStable[get_I_TBS(dlsch0_harq->mcs)][2];
      else AssertFatal(1==0,"Don't know how to set TBS (TPC %d)\n",rel13->tpc);
      LOG_D(PHY,"fill_mdci_and_dlsch : TBS = %d(%d) %p, %x\n",dlsch0_harq->TBS,dlsch0_harq->mcs,dlsch0,rel13->rnti);
    }
    dlsch0->active = 1;
    dlsch0->harq_mask |= (1 << rel13->harq_process);
  
    dlsch0_harq->frame    = (subframe >= 8) ? ((frame + 1) & 1023) : frame;
    dlsch0_harq->subframe = (subframe + 2) % 10;
  
    LOG_D(PHY,"Setting DLSCH UEid %d harq_ids[%d] from %d to %d\n",UE_id,dlsch0_harq->subframe,dlsch0->harq_ids[frame%2][dlsch0_harq->subframe],rel13->harq_process);
    dlsch0->harq_ids[dlsch0_harq->frame%2][dlsch0_harq->subframe] = rel13->harq_process;
    dlsch0_harq->pdsch_start = rel13->start_symbol;
  
    LOG_D(PHY,"Setting DLSCH harq %d round %d to active for %d.%d\n",rel13->harq_process,dlsch0_harq->round,dlsch0_harq->frame,dlsch0_harq->subframe);
  
    dlsch0->rnti = rel13->rnti;
  
    dlsch0_harq->Qm = get_Qm(rel13->mcs);
  
  
  
  
  
  }
  
  void fill_dci0(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t *proc,
      DCI_ALLOC_t *dci_alloc,nfapi_hi_dci0_dci_pdu *pdu)
  {
    LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
  
    uint32_t        cqi_req = pdu->dci_pdu_rel8.cqi_csi_request;
    uint32_t        dai = pdu->dci_pdu_rel8.dl_assignment_index;
    uint32_t        cshift = pdu->dci_pdu_rel8.cyclic_shift_2_for_drms;
    uint32_t        TPC = pdu->dci_pdu_rel8.tpc;
    uint32_t        mcs = pdu->dci_pdu_rel8.mcs_1;
    uint32_t        hopping = pdu->dci_pdu_rel8.frequency_hopping_enabled_flag;
    uint32_t        rballoc = computeRIV (frame_parms->N_RB_DL,
                                          pdu->dci_pdu_rel8.resource_block_start,
                                          pdu->dci_pdu_rel8.number_of_resource_block);
  
    uint32_t        ndi = pdu->dci_pdu_rel8.new_data_indication_1;
  
    uint16_t UE_id   = -1;
  
  #ifdef T_TRACER
    T(T_ENB_PHY_ULSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
      T_INT(pdu->dci_pdu_rel8.rnti), T_INT(pdu->dci_pdu_rel8.harq_pid),
      T_INT(mcs), T_INT(-1 /* TODO: remove round? */),
      T_INT(pdu->dci_pdu_rel8.resource_block_start),
      T_INT(pdu->dci_pdu_rel8.number_of_resource_block),
      T_INT(get_TBS_UL(mcs, pdu->dci_pdu_rel8.number_of_resource_block) * 8),
      T_INT(pdu->dci_pdu_rel8.aggregation_level),
      T_INT(pdu->dci_pdu_rel8.cce_index));
  #endif
  
    void           *dci_pdu = (void *) dci_alloc->dci_pdu;
  
    LOG_D(PHY,"SFN/SF:%04d%d DCI0[rnti %x cqi %d mcs %d hopping %d rballoc %x (%d,%d) ndi %d TPC %d cshift %d]\n",
          frame,subframe,
          pdu->dci_pdu_rel8.rnti,cqi_req, mcs,hopping,rballoc,
          pdu->dci_pdu_rel8.resource_block_start,
          pdu->dci_pdu_rel8.number_of_resource_block, ndi,TPC,cshift);
  
    dci_alloc->format = format0;
    dci_alloc->firstCCE = pdu->dci_pdu_rel8.cce_index;
    dci_alloc->L = pdu->dci_pdu_rel8.aggregation_level;
    dci_alloc->rnti = pdu->dci_pdu_rel8.rnti;
    dci_alloc->ra_flag = 0;
  
    switch (frame_parms->N_RB_DL) {
    case 6:
      if (frame_parms->frame_type == TDD) {
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->dai = dai;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->cshift = cshift;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->TPC = TPC;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->mcs = mcs;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->ndi = ndi;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->hopping = hopping;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->type = 0;
        ((DCI0_1_5MHz_TDD_1_6_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_1_5MHz_TDD_1_6_t;
      } else {
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->cshift = cshift;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->TPC = TPC;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->mcs = mcs;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->ndi = ndi;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->hopping = hopping;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->type = 0;
        ((DCI0_1_5MHz_FDD_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_1_5MHz_FDD_t;
      }
  
      break;
  
    case 25:
      if (frame_parms->frame_type == TDD) {
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->dai = dai;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->cshift = cshift;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->TPC = TPC;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->mcs = mcs;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->ndi = ndi;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->hopping = hopping;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->type = 0;
        ((DCI0_5MHz_TDD_1_6_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_5MHz_TDD_1_6_t;
      } else {
        ((DCI0_5MHz_FDD_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->cshift = cshift;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->TPC = TPC;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->mcs = mcs;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->ndi = ndi;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->hopping = hopping;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->type = 0;
        ((DCI0_5MHz_FDD_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_5MHz_FDD_t;
      }
  
      break;
  
    case 50:
      if (frame_parms->frame_type == TDD) {
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->dai = dai;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->cshift = cshift;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->TPC = TPC;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->mcs = mcs;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->ndi = ndi;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->hopping = hopping;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->type = 0;
        ((DCI0_10MHz_TDD_1_6_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_10MHz_TDD_1_6_t;
      } else {
        ((DCI0_10MHz_FDD_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->cshift = cshift;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->TPC = TPC;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->mcs = mcs;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->ndi = ndi;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->hopping = hopping;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->type = 0;
        ((DCI0_10MHz_FDD_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_10MHz_FDD_t;
      }
  
      break;
  
    case 100:
      if (frame_parms->frame_type == TDD) {
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->dai = dai;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->cshift = cshift;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->TPC = TPC;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->mcs = mcs;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->ndi = ndi;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->hopping = hopping;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->type = 0;
        ((DCI0_20MHz_TDD_1_6_t *) dci_pdu)->padding = 0;
  
        dci_alloc->dci_length = sizeof_DCI0_20MHz_TDD_1_6_t;
      } else {
        ((DCI0_20MHz_FDD_t *) dci_pdu)->cqi_req = cqi_req;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->cshift = cshift;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->TPC = TPC;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->mcs = mcs;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->ndi = ndi;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->rballoc = rballoc;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->hopping = hopping;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->type = 0;
        ((DCI0_20MHz_FDD_t *) dci_pdu)->padding = 0;
        dci_alloc->dci_length = sizeof_DCI0_20MHz_FDD_t;
      }
  
      //printf("eNB: rb_alloc (20 MHz dci) %d\n",rballoc);
      break;
  
    default:
      LOG_E (PHY, "Invalid N_RB_DL %d\n", frame_parms->N_RB_DL);
      DevParam (frame_parms->N_RB_DL, 0, 0);
      break;
    }
  
    if(frame_parms->frame_type == TDD){
       UE_id = find_ulsch(pdu->dci_pdu_rel8.rnti, eNB,SEARCH_EXIST_OR_FREE);
       if(UE_id != -1){
         eNB->ulsch[UE_id]->harq_processes[pdu->dci_pdu_rel8.harq_pid]->V_UL_DAI = dai +1;
       }
    }
  }
  
  
  #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
  int get_narrowband_index(int N_RB_UL,int rb) {
  
    switch (N_RB_UL) {
    case 6: // 6 PRBs, N_NB=1, i_0=0
    case 25: // 25 PRBs, N_NB=4, i_0=0
      return(rb/6);
      break;
    case 50: // 50 PRBs, N_NB=8, i_0=1
    case 75: // 75 PRBs, N_NB=12, i_0=1
    case 15: // 15 PRBs, N_NB=2, i_0=1
      AssertFatal(rb>=1,"rb %d is not possible for %d PRBs\n",rb,N_RB_UL);
      return((rb-1)/6);
      break;
    case 100: // 100 PRBs, N_NB=16, i_0=2
      AssertFatal(rb>=2,"rb %d is not possible for %d PRBs\n",rb,N_RB_UL);
      return(rb-2/6);
      break;
    default:
      AssertFatal(1==0,"Impossible N_RB_UL %d\n",N_RB_UL);
      break;
    }
  
  }
  #endif
  
  void fill_ulsch(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_ulsch_pdu *ulsch_pdu,int frame,int subframe)
  {
    uint8_t harq_pid;
    //uint8_t UE_id;
    boolean_t new_ulsch = (find_ulsch(ulsch_pdu->ulsch_pdu_rel8.rnti,eNB,SEARCH_EXIST)==-1) ? TRUE : FALSE;
  
    //AssertFatal((UE_id=find_ulsch(ulsch_pdu->ulsch_pdu_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE))>=0,
    //        "No existing/free UE ULSCH for rnti %x\n",ulsch_pdu->ulsch_pdu_rel8.rnti);
  
    LTE_eNB_ULSCH_t *ulsch=eNB->ulsch[UE_id];
    LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
  
    int use_srs = 0;
  
    harq_pid = ulsch_pdu->ulsch_pdu_rel8.harq_process_number;
  
    ulsch->harq_mask |= 1 << harq_pid;
  
  #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
    LOG_D(PHY,"Filling ULSCH : ue_type %d, harq_pid %d\n",ulsch->ue_type,harq_pid);
    ulsch->ue_type = ulsch_pdu->ulsch_pdu_rel13.ue_type;
    AssertFatal(harq_pid ==0 || ulsch->ue_type == NOCE, "Harq PID is not zero for BL/CE UE\n");
  
  
  #else
    ulsch->ue_type = 0;
  #endif
  
    if(ulsch_pdu->ulsch_pdu_rel13.repetition_number >1)	// Fill the Harq process parameters in the first Rep only
    {
  	  return;
    }
  
    //AssertFatal(ulsch->harq_processes[harq_pid]->nb_rb>0,"nb_rb = 0\n");
    if(ulsch->harq_processes[harq_pid]->nb_rb == 0){
      LOG_E(PHY, "fill_ulsch UE_id %d nb_rb = 0\n", UE_id);
    }
  
    ulsch->harq_processes[harq_pid]->frame                                 = frame;
    ulsch->harq_processes[harq_pid]->subframe                              = subframe;
    ulsch->harq_processes[harq_pid]->handled                               = 0;
  
    ulsch->harq_processes[harq_pid]->repetition_number			 = ulsch_pdu->ulsch_pdu_rel13.repetition_number ;
    ulsch->harq_processes[harq_pid]->total_number_of_repetitions		 = ulsch_pdu->ulsch_pdu_rel13.total_number_of_repetitions ;
  
    ulsch->harq_processes[harq_pid]->first_rb                              = ulsch_pdu->ulsch_pdu_rel8.resource_block_start;
    ulsch->harq_processes[harq_pid]->nb_rb                                 = ulsch_pdu->ulsch_pdu_rel8.number_of_resource_blocks;
  
  
    ulsch->harq_processes[harq_pid]->dci_alloc                             = 1;
    ulsch->harq_processes[harq_pid]->rar_alloc                             = 0;
    ulsch->harq_processes[harq_pid]->n_DMRS                                = ulsch_pdu->ulsch_pdu_rel8.cyclic_shift_2_for_drms;
    
    ulsch->harq_processes[harq_pid]->Nsymb_pusch                           = 12-(frame_parms->Ncp<<1)-(use_srs==0?0:1);
    ulsch->harq_processes[harq_pid]->srs_active                            = use_srs;
    
    //Mapping of cyclic shift field in DCI format0 to n_DMRS2 (3GPP 36.211, Table 5.5.2.1.1-1)
    if(ulsch->harq_processes[harq_pid]->n_DMRS == 0)
      ulsch->harq_processes[harq_pid]->n_DMRS2 = 0;
    else if(ulsch->harq_processes[harq_pid]->n_DMRS == 1)
      ulsch->harq_processes[harq_pid]->n_DMRS2 = 6;
    else if(ulsch->harq_processes[harq_pid]->n_DMRS == 2)
      ulsch->harq_processes[harq_pid]->n_DMRS2 = 3;
    else if(ulsch->harq_processes[harq_pid]->n_DMRS == 3)
      ulsch->harq_processes[harq_pid]->n_DMRS2 = 4;
    else if(ulsch->harq_processes[harq_pid]->n_DMRS == 4)
      ulsch->harq_processes[harq_pid]->n_DMRS2 = 2;
    else if(ulsch->harq_processes[harq_pid]->n_DMRS == 5)
      ulsch->harq_processes[harq_pid]->n_DMRS2 = 8;
    else if(ulsch->harq_processes[harq_pid]->n_DMRS == 6)
      ulsch->harq_processes[harq_pid]->n_DMRS2 = 10;
    else if(ulsch->harq_processes[harq_pid]->n_DMRS == 7)
      ulsch->harq_processes[harq_pid]->n_DMRS2 = 9;
    
    LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d, Subframe %d Programming PUSCH with n_DMRS2 %d (cshift %d) ulsch:ndi:%d ulsch_pdu:ndi:%d new_ulsch:%d status:%d ulsch_pdu:rvidx:%d ulsch_pdu->ulsch_pdu_rel8.size %d\n",
  	eNB->Mod_id,harq_pid,frame,subframe,
          ulsch->harq_processes[harq_pid]->n_DMRS2,
          ulsch->harq_processes[harq_pid]->n_DMRS,
  	ulsch->harq_processes[harq_pid]->ndi, ulsch_pdu->ulsch_pdu_rel8.new_data_indication, new_ulsch, ulsch->harq_processes[harq_pid]->status,
  	ulsch_pdu->ulsch_pdu_rel8.redundancy_version,
          ulsch_pdu->ulsch_pdu_rel8.size);
    
    ulsch->harq_processes[harq_pid]->rvidx = ulsch_pdu->ulsch_pdu_rel8.redundancy_version;
    if(ulsch_pdu->ulsch_pdu_rel8.modulation_type!=0)
    ulsch->harq_processes[harq_pid]->Qm    = ulsch_pdu->ulsch_pdu_rel8.modulation_type;
    // Set O_ACK to 0 by default, will be set of DLSCH is scheduled and needs to be 
    ulsch->harq_processes[harq_pid]->O_ACK         = 0;
  
    if ((ulsch->harq_processes[harq_pid]->status == SCH_IDLE) ||
        (ulsch->harq_processes[harq_pid]->ndi    != ulsch_pdu->ulsch_pdu_rel8.new_data_indication) ||
  	  (new_ulsch == TRUE)){
      ulsch->harq_processes[harq_pid]->status        = ACTIVE;
      
      ulsch->harq_processes[harq_pid]->TBS           = ulsch_pdu->ulsch_pdu_rel8.size<<3;
      
      ulsch->harq_processes[harq_pid]->Msc_initial   = 12*ulsch_pdu->ulsch_pdu_rel8.number_of_resource_blocks;
      ulsch->harq_processes[harq_pid]->Nsymb_initial = ulsch->harq_processes[harq_pid]->Nsymb_pusch;
      ulsch->harq_processes[harq_pid]->round         = 0;
      ulsch->harq_processes[harq_pid]->ndi           = ulsch_pdu->ulsch_pdu_rel8.new_data_indication;
      // note here, the CQI bits need to be kept constant as in initial transmission
      // set to 0 in initial transmission, and don't touch them during retransmissions
      // will be set if MAC has activated ULSCH_CQI_RI_PDU or ULSCH_CQI_HARQ_RI_PDU
      ulsch->harq_processes[harq_pid]->Or1           = 0;
      ulsch->harq_processes[harq_pid]->Or2           = 0;
    }
    else {
        ulsch->harq_processes[harq_pid]->round++;
        ulsch->harq_processes[harq_pid]->TBS           = ulsch_pdu->ulsch_pdu_rel8.size<<3;
        ulsch->harq_processes[harq_pid]->Msc_initial   = 12*ulsch_pdu->ulsch_pdu_rel8.number_of_resource_blocks;
    }
    ulsch->rnti = ulsch_pdu->ulsch_pdu_rel8.rnti;
    LOG_D(PHY,"Filling ULSCH %x (UE_id %d) (new_ulsch %d) for Frame %d, Subframe %d : harq_pid %d, status %d, handled %d, first_rb %d, nb_rb %d, rvidx %d, Qm %d, TBS %d, round %d \n",
  	ulsch->rnti,
          UE_id,
          new_ulsch,
  	frame,
  	subframe,
  	harq_pid,
  	ulsch->harq_processes[harq_pid]->status,
  	ulsch->harq_processes[harq_pid]->handled,
  	ulsch->harq_processes[harq_pid]->first_rb,
  	ulsch->harq_processes[harq_pid]->nb_rb,
  	ulsch->harq_processes[harq_pid]->rvidx,
  	ulsch->harq_processes[harq_pid]->Qm,
  	ulsch->harq_processes[harq_pid]->TBS,
  	ulsch->harq_processes[harq_pid]->round);  
  }
  
  
  #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
  
  int get_first_rb_in_narrowband(int N_RB_UL,int rb) {
  
    switch (N_RB_UL) {
    case 6: // 6 PRBs, N_NB=1, i_0=0
    case 25: // 25 PRBs, N_NB=4, i_0=0
      return(rb - 6*(rb/6));
      break;
    case 50: // 50 PRBs, N_NB=8, i_0=1
    case 75: // 75 PRBs, N_NB=12, i_0=1
    case 15: // 15 PRBs, N_NB=2, i_0=1
      AssertFatal(rb>=1,"rb %d is not possible for %d PRBs\n",rb,N_RB_UL);
      return(rb-1-(6*((rb-1)/6)));
      break;
    case 100: // 100 PRBs, N_NB=16, i_0=2
      AssertFatal(rb>=2,"rb %d is not possible for %d PRBs\n",rb,N_RB_UL);
      return(rb-2-(6*((rb-2)/6)));
      break;
    default:
      AssertFatal(1==0,"Impossible N_RB_UL %d\n",N_RB_UL);
      break;
    }
  }
  
  void fill_mpdcch_dci0 (PHY_VARS_eNB * eNB, L1_rxtx_proc_t * proc, mDCI_ALLOC_t * dci_alloc, nfapi_hi_dci0_mpdcch_dci_pdu * pdu)
  {
    LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
    nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t *rel13 = &pdu->mpdcch_dci_pdu_rel13;
  
    uint32_t        cqi_req = rel13->csi_request;
    uint32_t        TPC = rel13->tpc;
    uint32_t        mcs = rel13->mcs;
    uint32_t        hopping = rel13->frequency_hopping_flag;
    uint32_t        narrowband = get_narrowband_index(frame_parms->N_RB_UL,rel13->resource_block_start);
    uint32_t        rballoc = computeRIV (6,
                                          get_first_rb_in_narrowband(frame_parms->N_RB_UL,rel13->resource_block_start),
                                          rel13->number_of_resource_blocks);
  
    uint32_t        ndi = rel13->new_data_indication;
  
  #ifdef T_TRACER
    T (T_ENB_PHY_ULSCH_UE_DCI, T_INT (eNB->Mod_id), T_INT (proc->frame_tx), T_INT (proc->subframe_tx),
       T_INT (rel13->rnti), T_INT (((proc->frame_tx * 10 + proc->subframe_tx + 4) % 8) /* TODO: correct harq pid */ ),
       T_INT (mcs), T_INT (-1 /* TODO: remove round? */ ),
       T_INT (rel13->resource_block_start),
       T_INT (rel13->number_of_resource_blocks),
       T_INT (get_TBS_UL (mcs, rel13->number_of_resource_blocks) * 8), T_INT (rel13->aggreagation_level), T_INT (rel13->ecce_index));
  #endif
  
    void           *dci_pdu = (void *) dci_alloc->dci_pdu;
  
    AssertFatal(rel13->ce_mode == 1 && rel13->dci_format == 4, "dci format 5 (CE_modeB) not supported yet\n");
  
  
    LOG_D (PHY, "Filling DCI6-0A with cqi %d, mcs %d, hopping %d, rballoc %x (%d,%d) ndi %d TPC %d\n", cqi_req,
           mcs, hopping, rballoc, rel13->resource_block_start, rel13->number_of_resource_blocks, ndi, TPC);
  
    dci_alloc->format = format6_0A;
    dci_alloc->firstCCE = rel13->ecce_index;
    dci_alloc->L = rel13->aggreagation_level;
    dci_alloc->rnti = rel13->rnti;
    dci_alloc->harq_pid = rel13->harq_process;
    dci_alloc->narrowband = rel13->mpdcch_narrowband;
    dci_alloc->number_of_prb_pairs = rel13->number_of_prb_pairs;
    dci_alloc->resource_block_assignment = rel13->resource_block_assignment;
    dci_alloc->transmission_type = rel13->mpdcch_transmission_type;
    dci_alloc->start_symbol = rel13->start_symbol;
    dci_alloc->ce_mode = rel13->ce_mode;
    dci_alloc->dmrs_scrambling_init = rel13->drms_scrambling_init;
    dci_alloc->i0 = rel13->initial_transmission_sf_io;
  
  
    switch (frame_parms->N_RB_DL) {
    case 6:
      if (frame_parms->frame_type == TDD) {
        AssertFatal(1==0,"TDD not supported for eMTC yet\n");
      } else {
        AssertFatal(1==0,"6 PRBS not supported for eMTC\n");
      }
  
      break;
  
    case 25:
      if (frame_parms->frame_type == TDD) {
        AssertFatal(1==0,"TDD not supported for eMTC yet\n");
      } else {
        dci_alloc->dci_length = sizeof_DCI6_0A_5MHz_t;
        ((DCI6_0A_5MHz_t *) dci_pdu)->type = 0;
        ((DCI6_0A_5MHz_t *) dci_pdu)->hopping = hopping;
        ((DCI6_0A_5MHz_t *) dci_pdu)->rballoc = rballoc;
        ((DCI6_0A_5MHz_t *) dci_pdu)->narrowband = narrowband;
        ((DCI6_0A_5MHz_t *) dci_pdu)->mcs = mcs;
        ((DCI6_0A_5MHz_t *) dci_pdu)->rep = rel13->pusch_repetition_levels;
        ((DCI6_0A_5MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
        ((DCI6_0A_5MHz_t *) dci_pdu)->ndi = ndi;
        ((DCI6_0A_5MHz_t *) dci_pdu)->rv_idx = rel13->redudency_version;
        ((DCI6_0A_5MHz_t *) dci_pdu)->TPC = TPC;
        ((DCI6_0A_5MHz_t *) dci_pdu)->csi_req = cqi_req;
        ((DCI6_0A_5MHz_t *) dci_pdu)->srs_req = rel13->srs_request;
        ((DCI6_0A_5MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
  
      }
  
      break;
  
    case 50:
      if (frame_parms->frame_type == TDD) {
        AssertFatal(1==0,"TDD not supported for eMTC yet\n");
      } else {
        dci_alloc->dci_length = sizeof_DCI6_0A_10MHz_t;
        ((DCI6_0A_10MHz_t *) dci_pdu)->type = 0;
        ((DCI6_0A_10MHz_t *) dci_pdu)->hopping = hopping;
        ((DCI6_0A_10MHz_t *) dci_pdu)->rballoc = rballoc;
        ((DCI6_0A_10MHz_t *) dci_pdu)->narrowband = narrowband;
        ((DCI6_0A_10MHz_t *) dci_pdu)->mcs = mcs;
        ((DCI6_0A_10MHz_t *) dci_pdu)->rep = rel13->pusch_repetition_levels;
        ((DCI6_0A_10MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
        ((DCI6_0A_10MHz_t *) dci_pdu)->ndi = ndi;
        ((DCI6_0A_10MHz_t *) dci_pdu)->rv_idx = rel13->redudency_version;
        ((DCI6_0A_10MHz_t *) dci_pdu)->TPC = TPC;
        ((DCI6_0A_10MHz_t *) dci_pdu)->csi_req = cqi_req;
        ((DCI6_0A_10MHz_t *) dci_pdu)->srs_req = rel13->srs_request;
        ((DCI6_0A_10MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
        LOG_D(PHY,"Frame %d, Subframe %d : Programming Format 6-0A DCI, type %d, hopping %d, narrowband %d, rballoc %x, mcs %d, rep %d, harq_pid %d, ndi %d, rv %d, TPC %d, csi_req %d, srs_req %d, dci_rep r%d => %x\n",
  	    proc->frame_tx,proc->subframe_tx,
  	    ((DCI6_0A_10MHz_t *) dci_pdu)->type,
  	    ((DCI6_0A_10MHz_t *) dci_pdu)->hopping,
  	    ((DCI6_0A_10MHz_t *) dci_pdu)->narrowband,
  	    ((DCI6_0A_10MHz_t *) dci_pdu)->rballoc,
  	    ((DCI6_0A_10MHz_t *) dci_pdu)->mcs,
  	    ((DCI6_0A_10MHz_t *) dci_pdu)->rep,
  	    ((DCI6_0A_10MHz_t *) dci_pdu)->harq_pid,
  	    ((DCI6_0A_10MHz_t *) dci_pdu)->ndi,
  	    ((DCI6_0A_10MHz_t *) dci_pdu)->rv_idx,
  	    ((DCI6_0A_10MHz_t *) dci_pdu)->TPC,
  	    ((DCI6_0A_10MHz_t *) dci_pdu)->csi_req,
  	    ((DCI6_0A_10MHz_t *) dci_pdu)->srs_req,
  	    ((DCI6_0A_10MHz_t *) dci_pdu)->dci_rep,
  	    ((uint32_t*)dci_pdu)[0]);
  
      }
  
      break;
  
    case 100:
      if (frame_parms->frame_type == TDD) {
        AssertFatal(1==0,"TDD not supported for eMTC yet\n");
      } else {
        dci_alloc->dci_length = sizeof_DCI6_0A_20MHz_t;
        ((DCI6_0A_20MHz_t *) dci_pdu)->type = 0;
        ((DCI6_0A_20MHz_t *) dci_pdu)->hopping = hopping;
        ((DCI6_0A_20MHz_t *) dci_pdu)->rballoc = rballoc;
        ((DCI6_0A_20MHz_t *) dci_pdu)->narrowband = narrowband;
        ((DCI6_0A_20MHz_t *) dci_pdu)->mcs = rel13->mcs;
        ((DCI6_0A_20MHz_t *) dci_pdu)->rep = rel13->pusch_repetition_levels;
        ((DCI6_0A_20MHz_t *) dci_pdu)->harq_pid = rel13->harq_process;
        ((DCI6_0A_20MHz_t *) dci_pdu)->ndi = ndi;
        ((DCI6_0A_20MHz_t *) dci_pdu)->rv_idx = rel13->redudency_version;
        ((DCI6_0A_20MHz_t *) dci_pdu)->TPC = TPC;
        ((DCI6_0A_20MHz_t *) dci_pdu)->csi_req = cqi_req;
        ((DCI6_0A_20MHz_t *) dci_pdu)->srs_req = rel13->srs_request;
        ((DCI6_0A_20MHz_t *) dci_pdu)->dci_rep = rel13->dci_subframe_repetition_number;
      }
  
      //printf("eNB: rb_alloc (20 MHz dci) %d\n",rballoc);
      break;
  
    default:
      LOG_E (PHY, "Invalid N_RB_DL %d\n", frame_parms->N_RB_DL);
      DevParam (frame_parms->N_RB_DL, 0, 0);
      break;
    }
  }
  #endif
  