Merge "[Epic-ID: ODUHIGH-556][Task-ID: ODUHIGH-570] UL Candidate Sel and Res Alloc...
[o-du/l2.git] / src / 5gnrsch / sch_common.c
index 9c0b206..c9967d8 100644 (file)
@@ -41,6 +41,7 @@ File:     sch_common.c
 #include "du_app_mac_inf.h"
 #include "mac_sch_interface.h"
 #include "sch.h"
+#include "sch_tmr.h"
 #include "sch_utils.h"
 
 /**
@@ -138,9 +139,9 @@ uint8_t schBroadcastSib1Alloc(SchCellCb *cell, SlotTimingInfo slotTime, DlBrdcst
    }
    
    dlBrdcstAlloc->crnti = SI_RNTI;
-   dmrs = cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.dmrs;
-   freqAlloc = cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc;
-   timeAlloc = cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschTimeAlloc;
+   dmrs = cell->sib1SchCfg.sib1PdcchCfg.dci[0].pdschCfg.dmrs;
+   freqAlloc = cell->sib1SchCfg.sib1PdcchCfg.dci[0].pdschCfg.pdschFreqAlloc;
+   timeAlloc = cell->sib1SchCfg.sib1PdcchCfg.dci[0].pdschCfg.pdschTimeAlloc;
    schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
 
    /* Find total symbols used including DMRS */
@@ -406,20 +407,20 @@ uint8_t fillUlSchedPucchDedicatedCfg(SchCellCb *cell, SchPucchCfg *pucchDedCfg,\
  *  @return  ROK/RFAILED
  **/
 
-uint16_t fillPucchResourceInfo(uint8_t ueId, SchPucchInfo *schPucchInfo, Inst inst, SlotTimingInfo slotInfo)
+uint16_t fillPucchResourceInfo(SchCellCb *cell, uint8_t ueId, SchPucchInfo *schPucchInfo, SlotTimingInfo slotInfo,\
+                                SchPdcchAllocInfo *pdcchAllocInfo)
 {
-   uint8_t ret = ROK,  ueIdx = 0, pucchIdx = 0;
-   SchCellCb  *cell = schCb[inst].cells[inst];
+   uint8_t ret = RFAILED,  ueIdx = 0, pucchIdx = 0;
+   uint8_t val_pri = 0, r_pucch = 0, cRSetIdx = 0;
+   uint16_t startPrb = 0, n_cce = 0, N_cce = 0;
    SchPucchCfgCmn *pucchCfg = NULLP;
-   SchBwpParams *ulBwp = NULLP;
-#ifdef NR_DRX 
+   SchBwpDlCfg *initialDlBwp = NULLP;
+   SchBwpUlCfg *initialUlBwp = NULLP;
    SchUeCb *ueCb = NULLP;
-#endif
-   uint16_t startPrb;
 
    ueIdx = ueId -1;
-#ifdef NR_DRX 
    ueCb = &(cell->ueCb[ueIdx]); 
+#ifdef NR_DRX 
    if(ueCb->ueDrxInfoPres)
    {
       if(!ueCb->drxUeCb.drxUlUeActiveStatus)
@@ -430,27 +431,71 @@ uint16_t fillPucchResourceInfo(uint8_t ueId, SchPucchInfo *schPucchInfo, Inst in
    {
       /* fill pucch dedicated cfg */
       ret = fillUlSchedPucchDedicatedCfg(cell,\
-       &cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellRecfg.initUlBwp.pucchCfg, &slotInfo, schPucchInfo);
+            &cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellRecfg.initUlBwp.pucchCfg, &slotInfo, schPucchInfo);
       if(ret == RFAILED)
       {
          memset(schPucchInfo, 0, sizeof(SchPucchInfo));
          DU_LOG("\nERROR  --> SCH : Filling PUCCH dedicated cfg failed at fillPucchResourceInfo()");
-        return ret;
+         return ret;
       }
    }
    else
    {
       /* fill pucch common cfg */
-      /* derive pucchResourceSet from schCellCfg */
       pucchCfg = &cell->cellCfg.ulCfgCommon.schInitialUlBwp.pucchCommon;
       pucchIdx = pucchCfg->pucchResourceCommon;
-      ulBwp = &cell->cellCfg.ulCfgCommon.schInitialUlBwp.bwp;
-      startPrb = ulBwp->freqAlloc.startPrb + pucchResourceSet[pucchIdx][3];
+      initialUlBwp   = &cell->cellCfg.ulCfgCommon.schInitialUlBwp;
+
+      /*As per Spec 38.213, Sec 9.2.1, StartPrb is determined by by DCI and PDCCH CCE location
+       * N_cce = Num of CCEs in COreset used for PDCCH
+       * n_cce = first index of CCE used for PDCCH
+       * val_pri = PUCCH resource indicator field in DCI format 1_0/1_1*/
+      /* derive pucchResourceSet from schCellCfg */
+      if(pdcchAllocInfo != NULLP)
+      {
+         for(cRSetIdx = 0; cRSetIdx < MAX_NUM_CRSET; cRSetIdx++ )
+         {
+            if(ueCb->pdcchInfo[cRSetIdx].cRSetRef->cRSetId == pdcchAllocInfo->cRSetId)
+            {
+               N_cce = ueCb->pdcchInfo[cRSetIdx].totalCceCount;
+               break;
+            }
+         }
+         n_cce = pdcchAllocInfo->cceIndex;
+      }
+      else
+      {
+         initialDlBwp   = &cell->cellCfg.dlCfgCommon.schInitialDlBwp;
+          /* derive the sib1 coreset0 params from table 13-1 spec 38.213 */
+         N_cce = coresetIdxTable[initialDlBwp->pdcchCommon.commonSearchSpace.coresetId][1] * \
+                   coresetIdxTable[initialDlBwp->pdcchCommon.commonSearchSpace.coresetId][2];
+         n_cce = 4;/*As per current Implementation, default value of cceIndex for CORESET0 is 4*/
+      }
+      val_pri = PUCCH_RES_IND;
+
+      /*Following calculation are derived from Spec 38.213, Sec 9.2.1*/
+      r_pucch = (floor((2 * n_cce)/N_cce)) + (2 * val_pri);
+
+      if((floor(r_pucch/8)) == 0)
+      {
+         startPrb = pucchResourceSet[pucchIdx][3] + (floor(r_pucch/pucchResourceSet[pucchIdx][4]));
+      }      
+      else if((floor(r_pucch/8)) == 1)
+      {
+         startPrb = initialUlBwp->bwp.freqAlloc.numPrb - 1 - pucchResourceSet[pucchIdx][3] - \
+                        (floor((r_pucch - 8)/pucchResourceSet[pucchIdx][4]));
+      }
+      else
+      {
+         DU_LOG("\nERROR  -->  SCH: Invalid value of r_pucch:%d (greater than 15) ", r_pucch);
+         memset(schPucchInfo, 0, sizeof(SchPucchInfo));
+         return ret;
+      }
       ret = allocatePrbUl(cell, slotInfo, pucchResourceSet[pucchIdx][1], pucchResourceSet[pucchIdx][2],\
             &startPrb, PUCCH_NUM_PRB_FORMAT_0_1_4);
       if (ret == ROK)
       {
-         schPucchInfo->fdAlloc.startPrb = ulBwp->freqAlloc.startPrb + pucchResourceSet[pucchIdx][3];
+         schPucchInfo->fdAlloc.startPrb = startPrb;
          schPucchInfo->fdAlloc.numPrb = PUCCH_NUM_PRB_FORMAT_0_1_4;
          schPucchInfo->tdAlloc.startSymb = pucchResourceSet[pucchIdx][1];
          schPucchInfo->tdAlloc.numSymb = pucchResourceSet[pucchIdx][2];
@@ -460,7 +505,7 @@ uint16_t fillPucchResourceInfo(uint8_t ueId, SchPucchInfo *schPucchInfo, Inst in
          schPucchInfo->srFlag  = true;
       }
    }
-   return ROK;
+   return ret;
 }
 
 /**
@@ -478,16 +523,17 @@ uint16_t fillPucchResourceInfo(uint8_t ueId, SchPucchInfo *schPucchInfo, Inst in
 uint8_t schUlResAlloc(SchCellCb *cell, Inst schInst)
 {
    int ret = ROK;
-#ifdef NR_DRX 
-   SchUeCb   *ueCb;
-#endif
+   uint8_t ueIdx = 0;
    UlSchedInfo ulSchedInfo;
    SchUlSlotInfo  *schUlSlotInfo = NULLP;
    SlotTimingInfo ulTimingInfo;
+   CmLList        *node = NULLP;
+   TotalPrbUsage  *ulTotalPrbUsage = NULLP;
+
    memset(&ulSchedInfo, 0, sizeof(UlSchedInfo));
 
    /* add PHY delta */
-   ADD_DELTA_TO_TIME(cell->slotInfo,ulTimingInfo,PHY_DELTA_UL+SCHED_DELTA, cell->numSlots);
+   ADD_DELTA_TO_TIME(cell->slotInfo,ulTimingInfo,gConfigInfo.gPhyDeltaUl+SCHED_DELTA, cell->numSlots);
 
    ulSchedInfo.cellId = cell->cellId;
    ulSchedInfo.slotIndInfo.cellId = ulSchedInfo.cellId;
@@ -496,52 +542,54 @@ uint8_t schUlResAlloc(SchCellCb *cell, Inst schInst)
 
    /* Schedule resources for PRACH */
    if(cell->firstSib1Transmitted)
-    schPrachResAlloc(cell, &ulSchedInfo, ulTimingInfo);
+      schPrachResAlloc(cell, &ulSchedInfo, ulTimingInfo);
 
    schUlSlotInfo = cell->schUlSlotInfo[ulTimingInfo.slot]; 
-   if(schUlSlotInfo->schPuschInfo)
+   if(schUlSlotInfo->puschPres)
    {
-      GET_CRNTI(ulSchedInfo.crnti, schUlSlotInfo->puschUe);
       /* Check the ue drx status if the UE is active for uplink scheduling or not  */
-#ifdef NR_DRX 
-      ueCb = schGetUeCb(cell, ulSchedInfo.crnti);
-      if(ueCb->ueDrxInfoPres)
+      ulSchedInfo.dataType |= SCH_DATATYPE_PUSCH;
+      for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
       {
-         if(!ueCb->drxUeCb.drxUlUeActiveStatus)
-            return RFAILED;
+         if(schUlSlotInfo->schPuschInfo[ueIdx] != NULLP)
+         {
+            memcpy(&ulSchedInfo.schPuschInfo[ueIdx], schUlSlotInfo->schPuschInfo[ueIdx],
+                         sizeof(SchPuschInfo));
+            SCH_FREE(schUlSlotInfo->schPuschInfo[ueIdx], sizeof(SchPuschInfo));
+            schUlSlotInfo->schPuschInfo[ueIdx] = NULL;
+         }
       }
-#endif
-      ulSchedInfo.dataType |= SCH_DATATYPE_PUSCH;
-      memcpy(&ulSchedInfo.schPuschInfo, schUlSlotInfo->schPuschInfo,
-           sizeof(SchPuschInfo));
-      SCH_FREE(schUlSlotInfo->schPuschInfo, sizeof(SchPuschInfo));
-      schUlSlotInfo->schPuschInfo = NULL;
    }
 
    if(schUlSlotInfo->pucchPres)
    {
-      GET_CRNTI(ulSchedInfo.crnti, schUlSlotInfo->pucchUe);
-      ret = fillPucchResourceInfo(schUlSlotInfo->pucchUe, &schUlSlotInfo->schPucchInfo, schInst, ulTimingInfo);
-      if (ret == ROK)
-      {
-         ulSchedInfo.dataType |= SCH_DATATYPE_UCI;
-         memcpy(&ulSchedInfo.schPucchInfo, &schUlSlotInfo->schPucchInfo,
-               sizeof(SchPucchInfo));
-      }
-      else
+      ulSchedInfo.dataType |= SCH_DATATYPE_UCI;
+      memcpy(&ulSchedInfo.schPucchInfo, &schUlSlotInfo->schPucchInfo,
+              (sizeof(SchPucchInfo) * MAX_NUM_UE));
+      memset(&schUlSlotInfo->schPucchInfo, 0, (sizeof(SchPucchInfo) * MAX_NUM_UE));
+   }
+
+   if(ulSchedInfo.dataType > 0)
+   {
+      /* Send msg to MAC */
+      ret = sendUlSchInfoToMac(&ulSchedInfo, schInst);
+      if(ret != ROK)
       {
-         return RFAILED;
+         DU_LOG("\nERROR  -->  SCH : Sending UL Sch info from SCH to MAC failed");
       }
-      memset(&schUlSlotInfo->schPucchInfo, 0, sizeof(SchPucchInfo));
    }
 
-   //send msg to MAC
-   ret = sendUlSchInfoToMac(&ulSchedInfo, schInst);
-   if(ret != ROK)
+   /* Update DL PRB Usage for all stats group which requested for DL Total PRB Usage */
+   node = cmLListFirst(&schCb[schInst].statistics.activeKpiList.ulTotPrbUseList);
+   while(node)
    {
-      DU_LOG("\nERROR  -->  SCH : Sending UL Sch info from SCH to MAC failed");
+      ulTotalPrbUsage = (TotalPrbUsage *)node->node;
+      ulTotalPrbUsage->numPrbUsedForTx += schUlSlotInfo->prbAlloc.numPrbAlloc;
+      ulTotalPrbUsage->totalPrbAvailForTx += MAX_NUM_RB;
+      node = node->next;
    }
 
+   /* Re-initialize UL Slot */
    schInitUlSlot(schUlSlotInfo);
    return ret;
 }
@@ -643,19 +691,19 @@ uint8_t schDlRsrcAllocMsg4(SchCellCb *cell, SlotTimingInfo msg4Time, uint8_t ueI
    pdcch->coresetCfg.shiftIndex = cell->cellCfg.phyCellId;
    pdcch->coresetCfg.precoderGranularity = 0; /* sameAsRegBundle */
    pdcch->numDlDci = 1;
-   pdcch->dci.rnti = cell->raCb[ueId-1].tcrnti;
-   pdcch->dci.scramblingId = cell->cellCfg.phyCellId;
-   pdcch->dci.scramblingRnti = 0;
-   pdcch->dci.cceIndex = 4; /* considering SIB1 is sent at cce 0-1-2-3 */
-   pdcch->dci.aggregLevel = 4;
-   pdcch->dci.beamPdcchInfo.numPrgs = 1;
-   pdcch->dci.beamPdcchInfo.prgSize = 1;
-   pdcch->dci.beamPdcchInfo.digBfInterfaces = 0;
-   pdcch->dci.beamPdcchInfo.prg[0].pmIdx = 0;
-   pdcch->dci.beamPdcchInfo.prg[0].beamIdx[0] = 0;
-   pdcch->dci.txPdcchPower.beta_pdcch_1_0 = 0;
-   pdcch->dci.txPdcchPower.powerControlOffsetSS = 0;
-   pdsch = &pdcch->dci.pdschCfg; 
+   pdcch->dci[0].rnti = cell->raCb[ueId-1].tcrnti;
+   pdcch->dci[0].scramblingId = cell->cellCfg.phyCellId;
+   pdcch->dci[0].scramblingRnti = 0;
+   pdcch->dci[0].cceIndex = 4; /* considering SIB1 is sent at cce 0-1-2-3 */
+   pdcch->dci[0].aggregLevel = 4;
+   pdcch->dci[0].beamPdcchInfo.numPrgs = 1;
+   pdcch->dci[0].beamPdcchInfo.prgSize = 1;
+   pdcch->dci[0].beamPdcchInfo.digBfInterfaces = 0;
+   pdcch->dci[0].beamPdcchInfo.prg[0].pmIdx = 0;
+   pdcch->dci[0].beamPdcchInfo.prg[0].beamIdx[0] = 0;
+   pdcch->dci[0].txPdcchPower.beta_pdcch_1_0 = 0;
+   pdcch->dci[0].txPdcchPower.powerControlOffsetSS = 0;
+   pdsch = &pdcch->dci[0].pdschCfg; 
    
    /* fill the PDSCH PDU */
    uint8_t cwCount = 0;
@@ -752,29 +800,36 @@ uint8_t schDlRsrcAllocMsg4(SchCellCb *cell, SlotTimingInfo msg4Time, uint8_t ueI
  *       Scheduling for Pucch Resource
  *
  * @params[in] SchCellCb *cell, SlotTimingInfo pucchTime, crnti
- * @params[in] SchUeCb *ueCb, bool isRetx, SchDlHqProcCb *hqP
+ * @params[in] SchUeCb *ueCb, SchDlHqProcCb *hqP, SchPdcchAllocInfo *pdcchAllocInfo
  * @return ROK     - success
  *         RFAILED - failure
  *
  *******************************************************************/
 
-uint16_t schAllocPucchResource(SchCellCb *cell, SlotTimingInfo pucchTime, uint16_t crnti,
-                               SchUeCb *ueCb, bool isRetx, SchDlHqProcCb *hqP)
+uint8_t schAllocPucchResource(SchCellCb *cell, uint8_t ueId, SlotTimingInfo pucchTime, SchUeCb *ueCb,\
+                                SchDlHqProcCb *hqP, SchPdcchAllocInfo *pdcchAllocInfo)
 {
+   uint8_t ret = RFAILED;
    uint16_t pucchSlot = 0;
    SchUlSlotInfo  *schUlSlotInfo = NULLP;
 
    pucchSlot = pucchTime.slot;
    schUlSlotInfo = cell->schUlSlotInfo[pucchSlot];
-   memset(&schUlSlotInfo->schPucchInfo, 0, sizeof(SchPucchInfo));
 
-   schUlSlotInfo->pucchPres = true;
+   ret = fillPucchResourceInfo(cell, ueId, &schUlSlotInfo->schPucchInfo[ueId - 1],\
+                                 pucchTime, pdcchAllocInfo);
+   if(ret != ROK)
+   {
+      return ret;  
+   }
+
+   schUlSlotInfo->pucchPres = true; 
    if(ueCb != NULLP)
    {
       /* set HARQ flag to true */
-      schUlSlotInfo->schPucchInfo.harqInfo.harqBitLength = 1; /* 1 bit for HARQ */
+      schUlSlotInfo->schPucchInfo[ueId - 1].harqInfo.harqBitLength = 1; /* 1 bit for HARQ */
       ADD_DELTA_TO_TIME(pucchTime, pucchTime, 3, cell->numSlots); /* SLOT_DELAY=3 */
-      cmLListAdd2Tail(&(ueCb->hqDlmap[pucchTime.slot]->hqList), &hqP->ulSlotLnk);
+      cmLListAdd2Tail(&(ueCb->hqDlmap[pucchTime.slot]->hqList), &hqP->dlSlotLnk);
    }
    return ROK;
 }
@@ -801,15 +856,16 @@ uint16_t schAllocPucchResource(SchCellCb *cell, SlotTimingInfo pucchTime, uint16
  * ****************************************************************/
 uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t crnti,
                 uint32_t tbSize, DlMsgSchInfo *dlMsgAlloc, uint16_t startPRB, uint8_t pdschStartSymbol,
-                uint8_t pdschNumSymbols, bool isRetx, SchDlHqProcCb *hqP)
+                uint8_t pdschNumSymbols, bool isRetx, SchDlHqProcCb *hqP, SchPdcchAllocInfo pdcchAllocInfo)
 {
-   uint8_t ueId=0;
-   uint8_t cwCount = 0;
+   uint8_t ueId=0, ssIdx = 0, cRSetIdx = 0;;
+   uint8_t cwCount = 0, rbgCount = 0, pdcchStartSymbol = 0;
    PdcchCfg *pdcch = NULLP;
    PdschCfg *pdsch = NULLP;
    BwpCfg *bwp = NULLP;
    SchUeCb ueCb;
    SchControlRsrcSet coreset1;
+   SchSearchSpace searchSpace;
    SchPdschConfig pdschCfg;
    uint8_t dmrsStartSymbol, startSymbol, numSymbol;
 
@@ -824,7 +880,25 @@ uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t c
 
    GET_UE_ID(crnti, ueId);
    ueCb  = cell->ueCb[ueId-1];
-   coreset1 = ueCb.ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdcchCfg.cRSetToAddModList[0];
+
+   for(cRSetIdx = 0; cRSetIdx < ueCb.ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdcchCfg.numCRsetToAddMod; cRSetIdx++)
+   {
+      if(ueCb.ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdcchCfg.cRSetToAddModList[cRSetIdx].cRSetId\
+            == pdcchAllocInfo.cRSetId)
+      {
+         coreset1 = ueCb.ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdcchCfg.cRSetToAddModList[cRSetIdx];
+         break;
+      }
+   }
+   for(ssIdx = 0; ssIdx < ueCb.ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdcchCfg.numSearchSpcToAddMod; ssIdx++)
+   {
+      if(ueCb.ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdcchCfg.searchSpcToAddModList[ssIdx].searchSpaceId\
+            ==  pdcchAllocInfo.ssId)
+      {
+         searchSpace = ueCb.ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdcchCfg.searchSpcToAddModList[ssIdx];
+         break;
+      }
+   }
    pdschCfg = ueCb.ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdschCfg;
 
    /* fill BWP */
@@ -834,33 +908,61 @@ uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t c
    bwp->cyclicPrefix = cell->sib1SchCfg.bwp.cyclicPrefix;
 
    /* fill the PDCCH PDU */
-   //Considering coreset1 also starts from same symbol as coreset0
-   pdcch->coresetCfg.startSymbolIndex = coresetIdxTable[0][3];
+   /*StartSymbol of PDCCH*/
+   pdcchStartSymbol = findSsStartSymbol(searchSpace.mSymbolsWithinSlot);
+   if(pdcchStartSymbol < MAX_SYMB_PER_SLOT)
+      pdcch->coresetCfg.startSymbolIndex = pdcchStartSymbol;
+   else
+   {
+      DU_LOG("\nERROR  -->  SCH : Invalid SymbolIndex in schDlRsrcAllocDlMsg");
+      return RFAILED;
+   }
    pdcch->coresetCfg.durationSymbols = coreset1.duration;
    memcpy(pdcch->coresetCfg.freqDomainResource, coreset1.freqDomainRsrc, FREQ_DOM_RSRC_SIZE);
    pdcch->coresetCfg.cceRegMappingType = coreset1.cceRegMappingType; /* non-interleaved */
    pdcch->coresetCfg.regBundleSize = 6;   /* must be 6 for non-interleaved */
    pdcch->coresetCfg.interleaverSize = 0; /* NA for non-interleaved */
    pdcch->coresetCfg.coreSetType = 1; /* non PBCH coreset */
-   //Considering number of RBs in coreset1 is same as coreset0
-   pdcch->coresetCfg.coreSetSize = coresetIdxTable[0][1];
+
+   /*Size of coreset: Number of PRBs in a coreset*/
+   rbgCount = countRBGFrmCoresetFreqRsrc(coreset1.freqDomainRsrc);
+   if(rbgCount)
+   {
+      pdcch->coresetCfg.coreSetSize = ((rbgCount) * NUM_PRBS_PER_RBG);
+   }
+   else
+   {
+      DU_LOG("\nERROR  -->  SCH : CORESETSize is zero in schDlRsrcAllocDlMsg");
+      return RFAILED;
+   }
+
    pdcch->coresetCfg.shiftIndex = cell->cellCfg.phyCellId;
    pdcch->coresetCfg.precoderGranularity =  coreset1.precoderGranularity;
-   pdcch->numDlDci = 1;
-   pdcch->dci.rnti = ueCb.crnti;
-   pdcch->dci.scramblingId = cell->cellCfg.phyCellId;
-   pdcch->dci.scramblingRnti = 0;
-   pdcch->dci.cceIndex = 0; /* 0-3 for UL and 4-7 for DL */
-   pdcch->dci.aggregLevel = 4;
-   pdcch->dci.beamPdcchInfo.numPrgs = 1;
-   pdcch->dci.beamPdcchInfo.prgSize = 1;
-   pdcch->dci.beamPdcchInfo.digBfInterfaces = 0;
-   pdcch->dci.beamPdcchInfo.prg[0].pmIdx = 0;
-   pdcch->dci.beamPdcchInfo.prg[0].beamIdx[0] = 0;
-   pdcch->dci.txPdcchPower.beta_pdcch_1_0 = 0;
-   pdcch->dci.txPdcchPower.powerControlOffsetSS = 0;
-
-   pdsch = &pdcch->dci.pdschCfg;
+   if(pdcch->numDlDci >= MAX_NUM_PDCCH)
+   {
+      DU_LOG("\nERROR  -->  SCH: MAX number of PDCCH allocted for this slot.");
+      return RFAILED;
+   }
+   pdcch->dci[pdcch->numDlDci].rnti = ueCb.crnti;
+   pdcch->dci[pdcch->numDlDci].scramblingId = cell->cellCfg.phyCellId;
+   pdcch->dci[pdcch->numDlDci].scramblingRnti = 0;
+
+   /*TODO below assumptions of CCE Index is wrong:
+    * Range 0 to 135 as per ORAN.WG8.AAD Table 9-35 CORESET configuration and
+    * it has to be calculated using the formula given in 3GPP TS 38.213, Sec 10.1 */
+   pdcch->dci[pdcch->numDlDci].cceIndex = pdcchAllocInfo.cceIndex; 
+   pdcch->dci[pdcch->numDlDci].aggregLevel = pdcchAllocInfo.aggLvl;
+   pdcch->dci[pdcch->numDlDci].beamPdcchInfo.numPrgs = 1;
+   pdcch->dci[pdcch->numDlDci].beamPdcchInfo.prgSize = 1;
+   pdcch->dci[pdcch->numDlDci].beamPdcchInfo.digBfInterfaces = 0;
+   pdcch->dci[pdcch->numDlDci].beamPdcchInfo.prg[0].pmIdx = 0;
+   pdcch->dci[pdcch->numDlDci].beamPdcchInfo.prg[0].beamIdx[0] = 0;
+   pdcch->dci[pdcch->numDlDci].txPdcchPower.beta_pdcch_1_0 = 0;
+   pdcch->dci[pdcch->numDlDci].txPdcchPower.powerControlOffsetSS = 0;
+
+   pdsch = &pdcch->dci[pdcch->numDlDci].pdschCfg;
+   pdcch->numDlDci++;
+
    pdsch->pduBitmap = 0; /* PTRS and CBG params are excluded */
    pdsch->rnti = ueCb.crnti;
    pdsch->pduIndex = 0;
@@ -920,7 +1022,7 @@ uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t c
 
    /* Allocate the number of PRBs required for DL PDSCH */
    if((allocatePrbDl(cell, slotTime, startSymbol, numSymbol,\
-      &pdsch->pdschFreqAlloc.startPrb, pdsch->pdschFreqAlloc.numPrb)) != ROK)
+               &pdsch->pdschFreqAlloc.startPrb, pdsch->pdschFreqAlloc.numPrb)) != ROK)
    {
       DU_LOG("\nERROR  --> SCH : allocatePrbDl() failed for DL MSG");
       SCH_FREE(dlMsgAlloc->dlMsgPdcchCfg, sizeof(PdcchCfg));
@@ -1092,7 +1194,7 @@ SchPdschConfig pdschDedCfg, uint8_t ulAckListCount, uint8_t *UlAckTbl)
       /* Initialization the K0K1 structure, total num of slot and calculating the slot pattern length. */
       memset(k0K1InfoTbl, 0, sizeof(SchK0K1TimingInfoTbl));
       k0K1InfoTbl->tblSize = cell->numSlots;
-      totalCfgSlot = calculateSlotPatternLength(cell->cellCfg.scsCommon, cell->cellCfg.tddCfg.tddPeriod);
+      totalCfgSlot = calculateSlotPatternLength(cell->cellCfg.ssbScs, cell->cellCfg.tddCfg.tddPeriod);
       
       /* Storing time domain resource allocation list based on common or 
        * dedicated configuration availability. */
@@ -1322,7 +1424,7 @@ SchK2TimingInfoTbl *msg3K2InfoTbl, SchK2TimingInfoTbl *k2InfoTbl)
       k2InfoTbl->tblSize = cell->numSlots;
       if(msg3K2InfoTbl)
          msg3K2InfoTbl->tblSize = cell->numSlots;
-      totalCfgSlot = calculateSlotPatternLength(cell->cellCfg.scsCommon, cell->cellCfg.tddCfg.tddPeriod);
+      totalCfgSlot = calculateSlotPatternLength(cell->cellCfg.ssbScs, cell->cellCfg.tddCfg.tddPeriod);
 
       /* Checking all possible indexes for K2. */
       for(slotIdx = 0; slotIdx < cell->numSlots; slotIdx++)
@@ -1340,7 +1442,7 @@ SchK2TimingInfoTbl *msg3K2InfoTbl, SchK2TimingInfoTbl *k2InfoTbl)
                k2Val = timeDomRsrcAllocList[k2Index].k2;
                if(!k2Val)
                {
-                  switch(cell->cellCfg.scsCommon)
+                  switch(cell->cellCfg.ssbScs)
                   {
                      case SCS_15KHZ:
                         k2Val = DEFAULT_K2_VALUE_FOR_SCS15;
@@ -1390,7 +1492,7 @@ SchK2TimingInfoTbl *msg3K2InfoTbl, SchK2TimingInfoTbl *k2InfoTbl)
 
                if(msg3K2InfoTbl)
                {
-                   msg3Delta = puschDeltaTable[cell->cellCfg.numerology];
+                   msg3Delta = puschDeltaTable[cell->numerology];
 
                   /* Check for K2 for MSG3 */
                   /* Current slot + k2 should be either UL or FLEXI slot.
@@ -1709,7 +1811,7 @@ void fillDlMsgInfo(DlMsgSchInfo *dlMsgSchInfo, uint16_t crnti, bool isRetx, SchD
    dlMsgSchInfo->harqProcNum = hqP->procId;
    dlMsgSchInfo->dlAssignIdx = 0;
    dlMsgSchInfo->pucchTpc = 0;
-   dlMsgSchInfo->pucchResInd = 0;
+   dlMsgSchInfo->pucchResInd = PUCCH_RES_IND;
    dlMsgSchInfo->harqFeedbackInd = hqP->k1;
    dlMsgSchInfo->dciFormatId = 1;
 }
@@ -1758,7 +1860,7 @@ uint8_t schProcessMsg4Req(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId
    }
 
    if(findValidK0K1Value(cell, currTime, ueId, false, &pdschStartSymbol, &pdschNumSymbols, &pdcchTime, &pdschTime,\
-            &pucchTime, isRetxMsg4, *msg4HqProc) != true )
+            &pucchTime, isRetxMsg4, *msg4HqProc, NULLP) != true )
    {
       DU_LOG("\nERROR  -->  SCH: schProcessMsg4Req() : k0 k1 not found");
       return RFAILED;
@@ -1804,7 +1906,7 @@ uint8_t schProcessMsg4Req(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId
          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
          return RFAILED;
       }
-      memcpy(dciSlotAlloc->dlMsgPdschCfg, &dciSlotAlloc->dlMsgPdcchCfg->dci.pdschCfg, sizeof(PdschCfg));
+      memcpy(dciSlotAlloc->dlMsgPdschCfg, &dciSlotAlloc->dlMsgPdcchCfg->dci[0].pdschCfg, sizeof(PdschCfg));
    }
    else
    {
@@ -1835,7 +1937,7 @@ uint8_t schProcessMsg4Req(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId
       SCH_ALLOC(msg4SlotAlloc->dlMsgPdschCfg, sizeof(PdschCfg));
       if(msg4SlotAlloc->dlMsgPdschCfg)
       {
-         memcpy(msg4SlotAlloc->dlMsgPdschCfg, &dciSlotAlloc->dlMsgPdcchCfg->dci.pdschCfg, sizeof(PdschCfg));
+         memcpy(msg4SlotAlloc->dlMsgPdschCfg, &dciSlotAlloc->dlMsgPdcchCfg->dci[0].pdschCfg, sizeof(PdschCfg));
       }
       else
       {
@@ -1853,12 +1955,8 @@ uint8_t schProcessMsg4Req(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId
       }
    }
 
-   /* PUCCH resource */
-   schAllocPucchResource(cell, pucchTime, cell->raCb[ueId-1].tcrnti, &cell->ueCb[ueId-1], isRetxMsg4, *msg4HqProc);
-
    cell->schDlSlotInfo[pdcchTime.slot]->pdcchUe = ueId;
-   cell->schDlSlotInfo[pdschTime.slot]->pdschUe = ueId;
-   cell->schUlSlotInfo[pucchTime.slot]->pucchUe = ueId;
+   
    cell->raCb[ueId-1].msg4recvd = FALSE;
    if(isRetxMsg4)
    {
@@ -1978,7 +2076,7 @@ bool schProcessSrOrBsrReq(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId
    }
 
    /* Calculating time frame to send DCI for SR */
-   ADD_DELTA_TO_TIME(currTime, dciTime, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
+   ADD_DELTA_TO_TIME(currTime, dciTime, gConfigInfo.gPhyDeltaDl + SCHED_DELTA, cell->numSlots);
 #ifdef NR_TDD
    if(schGetSlotSymbFrmt(dciTime.slot, cell->slotFrmtBitMap) == DL_SLOT)
 #endif
@@ -2011,7 +2109,8 @@ bool schProcessSrOrBsrReq(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId
          if(schGetSlotSymbFrmt(puschTime.slot, cell->slotFrmtBitMap) == DL_SLOT)
             continue;
 #endif
-         if(cell->schUlSlotInfo[puschTime.slot]->puschUe != 0)
+         if((cell->schUlSlotInfo[puschTime.slot]->schPuschInfo[ueId - 1] != NULLP) 
+              && cell->schUlSlotInfo[puschTime.slot]->schPuschInfo[ueId - 1]->crnti == ueCb->crnti)
          {
             continue;
          }
@@ -2031,7 +2130,7 @@ bool schProcessSrOrBsrReq(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId
    }
    else
    {
-      DU_LOG("\nDEBUG  -->  SCH : schProcessSrOrBsrReq(): K2 value is not found");
+      /* K2 value not found*/
       return false;     
    }
    return true;
@@ -2161,7 +2260,7 @@ uint8_t schMsg3RetxSchedulingForUe(SchRaCb *raCb)
    currTime = cell->slotInfo;
 
    /* Calculating time frame to send DCI for MSG3 Retx*/
-   ADD_DELTA_TO_TIME(currTime, dciTime, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
+   ADD_DELTA_TO_TIME(currTime, dciTime, gConfigInfo.gPhyDeltaDl + SCHED_DELTA, cell->numSlots);
 #ifdef NR_TDD
    /* Consider this slot for sending DCI, only if it is a DL slot */
    if(schGetSlotSymbFrmt(dciSlot, raCb->cell->slotFrmtBitMap) == DL_SLOT)
@@ -2171,7 +2270,7 @@ uint8_t schMsg3RetxSchedulingForUe(SchRaCb *raCb)
       if(cell->schDlSlotInfo[dciSlot]->pdcchUe != 0)
          return false;
 
-      k2Found = schGetMsg3K2(cell, &raCb->msg3HqProc, dciTime.slot, &msg3Time, TRUE);
+      k2Found = schGetMsg3K2(cell, raCb->ueId,  &raCb->msg3HqProc, dciTime.slot, &msg3Time, TRUE);
 
       if (!k2Found)
       {
@@ -2184,9 +2283,10 @@ uint8_t schMsg3RetxSchedulingForUe(SchRaCb *raCb)
          return RFAILED;
       }
       cell->schDlSlotInfo[msg3Time.slot]->ulGrant = dciInfo;
-      SCH_ALLOC(cell->schUlSlotInfo[msg3Time.slot]->schPuschInfo, sizeof(SchPuschInfo));
+      SCH_ALLOC(cell->schUlSlotInfo[msg3Time.slot]->schPuschInfo[raCb->ueId - 1], sizeof(SchPuschInfo));
+      cell->schUlSlotInfo[msg3Time.slot]->puschPres = true;
       memset(dciInfo,0,sizeof(DciInfo));
-      schFillUlDciForMsg3Retx(raCb, cell->schUlSlotInfo[msg3Time.slot]->schPuschInfo, dciInfo);
+      schFillUlDciForMsg3Retx(raCb, cell->schUlSlotInfo[msg3Time.slot]->schPuschInfo[raCb->ueId - 1], dciInfo);
    }   
    raCb->retxMsg3HqProc = NULLP;
    return ROK;
@@ -2210,7 +2310,7 @@ uint8_t schMsg3RetxSchedulingForUe(SchRaCb *raCb)
  *      -# true
  *      -# false
  **/
-bool schGetMsg3K2(SchCellCb *cell, SchUlHqProcCb* msg3HqProc, uint16_t dlTime, SlotTimingInfo *msg3Time, bool isRetx)
+bool schGetMsg3K2(SchCellCb *cell, uint8_t ueId, SchUlHqProcCb* msg3HqProc, uint16_t dlTime, SlotTimingInfo *msg3Time, bool isRetx)
 {
    bool      k2Found = false;
    uint8_t   k2TblIdx = 0;
@@ -2222,10 +2322,11 @@ bool schGetMsg3K2(SchCellCb *cell, SchUlHqProcCb* msg3HqProc, uint16_t dlTime, S
 #ifdef NR_TDD
    uint8_t   totalCfgSlot = 0;
 #endif
+   uint16_t crnti = 0;
    SchK2TimingInfoTbl   *msg3K2InfoTbl=NULLP;
    SlotTimingInfo       currTime, msg3TempTime;
    currTime = cell->slotInfo;
-   puschMu = cell->cellCfg.numerology;
+   puschMu = cell->numerology;
 
    if (isRetx)
    {
@@ -2241,10 +2342,11 @@ bool schGetMsg3K2(SchCellCb *cell, SchUlHqProcCb* msg3HqProc, uint16_t dlTime, S
    {
       numK2 = cell->msg3K2InfoTbl.k2TimingInfo[dlTime].numK2;
       msg3K2InfoTbl = &cell->k2InfoTbl;
-      msg3MinSchTime = minMsg3SchTime[cell->cellCfg.numerology];
+      msg3MinSchTime = minMsg3SchTime[cell->numerology];
       msg3Delta = puschDeltaTable[puschMu];
    }
-
+   GET_UE_ID(crnti, ueId);
    for(k2TblIdx = 0; k2TblIdx < numK2; k2TblIdx++)
    {
       k2Index = msg3K2InfoTbl->k2TimingInfo[dlTime].k2Indexes[k2TblIdx];
@@ -2267,9 +2369,10 @@ bool schGetMsg3K2(SchCellCb *cell, SchUlHqProcCb* msg3HqProc, uint16_t dlTime, S
          if(schGetSlotSymbFrmt(msg3TempTime.slot % totalCfgSlot, cell->slotFrmtBitMap) == DL_SLOT)
             continue;
 #endif
-         /* If PUSCH is already scheduled on this slot, another PUSCH
-          * pdu cannot be scheduled here */
-         if(cell->schUlSlotInfo[msg3TempTime.slot]->puschUe != 0)
+         /* If PUSCH is already scheduled on this slot for this UE, another PUSCH
+          * pdu cannot be scheduled here for same UE*/
+         if((cell->schUlSlotInfo[msg3TempTime.slot]->schPuschInfo[ueId - 1] != NULLP) 
+              && cell->schUlSlotInfo[msg3TempTime.slot]->schPuschInfo[ueId - 1]->crnti == crnti)
             continue;
          k2Found = true;
          break;
@@ -2284,6 +2387,277 @@ bool schGetMsg3K2(SchCellCb *cell, SchUlHqProcCb* msg3HqProc, uint16_t dlTime, S
    return k2Found;
 }
 
+/*
+ *  * @brief : This Function fills the Coreset and SS info based on PDCCH Cfg received for a UE
+ *
+ *     Function : fillUeCoresetAndSsInfo
+ *
+ * For a Coreset, capture the following details which will be used during pdcch allocation
+ *   [Step 1]: Count number of RBG and calculate TotalPRBs which can be used 
+ *   [Step 2]: Get the reference pointer for Coreset and Its SearchSpace.
+ *   [Step 3]: A CCE will have 6 RBs in TOTAL. If duration increases, CCE will
+ *             occupy less number of PRBs(1RB x 1 OFDM Symbol). Eg. If duration = 2, then
+ *             instead of 6 PRBs, CCE will only occupy 3 PRBs and 2 OFDM symbols.
+ *   [Step 4]: Based on CoresetSize, fill AggLvl-CQI mapping by calculating the dciSize.
+ *   [Step 5]: Calculate Y value for this coreset and UE
+ *
+ *   @Params[in]: UeCb,
+ *  [return]: ROK, RFAILED : Memory allocation failure.
+ **/
+uint8_t fillUeCoresetAndSsInfo(SchUeCb *ue)
+{
+   uint8_t  cRSetIdx = 0,ssIdx = 0; 
+   uint16_t rbgCount = 0;
+   SchPdcchConfig *pdcchCfg = NULLP;
+
+   pdcchCfg =  &ue->ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdcchCfg;
+   if(pdcchCfg == NULLP)
+   {
+     DU_LOG("\nERROR  --> SCH: PDCCH Cfg is not received thus skip filling of Coreset & SS info");
+     return RFAILED;
+   }
+   for(cRSetIdx = 0; cRSetIdx < pdcchCfg->numCRsetToAddMod; cRSetIdx++ )
+   {
+      /*[Step 1]: *//*Size of coreset: Number of PRBs in a coreset*/
+      rbgCount = countRBGFrmCoresetFreqRsrc(pdcchCfg->cRSetToAddModList[cRSetIdx].freqDomainRsrc);
+      if(rbgCount)
+      {
+         ue->pdcchInfo[cRSetIdx].totalPrbs = ((rbgCount) * NUM_PRBS_PER_RBG);
+      }
+      else
+      {
+         DU_LOG("\nERROR  -->  SCH : CORESETSize is zero in fillCoresetAndSsConfg");
+         continue;
+      }
+      /*[Step 2]:*/
+      ue->pdcchInfo[cRSetIdx].cRSetRef = &pdcchCfg->cRSetToAddModList[cRSetIdx];
+      for(ssIdx = 0; ssIdx < pdcchCfg->numSearchSpcToAddMod; ssIdx++)
+      {
+         if(pdcchCfg->searchSpcToAddModList[ssIdx].cRSetId == pdcchCfg->cRSetToAddModList[cRSetIdx].cRSetId)
+         {
+            ue->pdcchInfo[cRSetIdx].ssRef = &pdcchCfg->searchSpcToAddModList[ssIdx];
+            break;
+         }
+      }
+
+      /*[Step 3]:*/
+      /*nrOfPRBPerCce is Number of PRBs occupied by a CCE based on Duration*/
+      ue->pdcchInfo[cRSetIdx].nrOfPRBPerCce = NUM_PRBS_PER_RBG/pdcchCfg->cRSetToAddModList[cRSetIdx].duration;
+      ue->pdcchInfo[cRSetIdx].totalCceCount = rbgCount * pdcchCfg->cRSetToAddModList[cRSetIdx].duration;
+
+      /*[Step 4]:*/
+      fillCqiAggLvlMapping(&ue->pdcchInfo[cRSetIdx]);
+
+      /*[Step 5]:*/
+      if(RFAILED == schUpdValY(ue, &ue->pdcchInfo[cRSetIdx]))
+      {
+         return RFAILED;
+      }
+   }
+   return ROK;
+}
+
+/*
+ *  @brief: Function will validate a slot for PDCCH allocation
+ *
+ *  Function: schPdcchSlotValidation
+ *
+ *  As per 3gpp Spec 38.331, SearchSpace parameter, Every SearchSpace will have
+ *  details of which slot and after how many slot the UE will monitor for PDCCH.
+ *  Thus, while PDCCH allocation we need to ensure the above validation passes.
+ *
+ *  @param [IN]: PDCCH time, SearchSpace Info, numSlots in Cell
+ *         [RETURN]: Flag depicting the slot validation
+ * */
+bool schPdcchSlotValidation(SlotTimingInfo pdcchTime, SchSearchSpace *searchSpace, uint16_t numSlots)
+{
+    bool     isSlotValid = false;
+    uint16_t slotNum = 0, mSlotPeriodicityVal = 0;
+
+    /*Converting the timing info in units of Slots*/
+    slotNum = (pdcchTime.sfn * numSlots)+pdcchTime.slot;
+
+    mSlotPeriodicityVal = \
+    schConvertSlotPeriodicityEnumToValue(searchSpace->mSlotPeriodicityAndOffset.mSlotPeriodicity);
+
+    if(!mSlotPeriodicityVal)
+    {
+       DU_LOG("\nERROR   --> SCH: Slot Periodicity is ZERO thus cant proceed with this SearchSpace");
+       return false;
+    }
+    /*The Monitoring slot begins from offset thus skip the slots which are less
+     * than offset value*/
+    if((slotNum >= searchSpace->mSlotPeriodicityAndOffset.mSlotOffset))
+    {
+        /*A pdcch Slot will start after Slotoffset and will get repeated after every
+         * SlotPeriodicity*/
+        if(((slotNum - searchSpace->mSlotPeriodicityAndOffset.mSlotOffset) % mSlotPeriodicityVal) == 0) 
+        {
+           DU_LOG("\nINFO   --> SCH: SFN:%d/Slot:%d, is a Valid PDCCH slot",pdcchTime.sfn, pdcchTime.slot);
+           isSlotValid = true;
+        }
+        else
+        {
+           DU_LOG("\nINFO   --> SCH: SFN:%d/Slot:%d, is InValid PDCCH slot",pdcchTime.sfn, pdcchTime.slot);
+        }
+    }
+    return (isSlotValid); 
+}
+
+/*
+ *  @brief: Function to check if PDCCH is available for a cceIndex
+ *
+ *  Function: schCheckPdcchAvail
+ *
+ *   This function checks if the PRBs available for a particular CCE during
+ *   PDCCH allocation
+ *   [Step 1]: Calculate the rbgIndex from cceIndex which depends on Coreset symbol duration
+ *   i.e. a) If symbolDuration = 1; numPrbs in RBG (6) = numPrbPerCCE thus one on
+ *        one mapping between rbgIndex and cceIndex
+ *        b) if SymbolDuration =2; NumPrbs in RBG(6) = numPrbPerCCE * duration
+ *        as CCE needs 6 REG thus in 3 PRBs whole CCE can contain 
+ *        c) and so on
+ *
+ *   [Step 2]: Again StartPRB for a rbgIndex may not be same for CCE Index which
+ *             depends on duration. If duration=2, then two CCE can be occupied
+ *             in one RBGIndex thus StarPrb for secondCCE will be
+ *             numPrbsPerCCE(3) away.
+ *
+ *   @params[in]: CellCb, SlotTime, cceIndex, PDcchInfo, aggLvl
+ * */
+bool schCheckPdcchAvail(SchCellCb *cellCb, SlotTimingInfo slotTime, uint8_t cceIndex,\
+                    SchPdcchInfo *pdcchInfo, uint8_t aggLvl )
+{
+    uint8_t rbgIndex = 0, ret = 0, startSymbol = 0;
+    uint16_t startPrb = MAX_NUM_RB, numPrb = 0;
+
+    /*[Step 1]: rbgIndex to locate in FreqDomainResource parmaeter in
+     * SearchSpace*/
+    rbgIndex = cceIndex / (pdcchInfo->cRSetRef->duration);
+   
+    /*Extract StartPRB for that RBGIndex*/
+    startPrb = extractStartPrbForRBG(pdcchInfo->cRSetRef->freqDomainRsrc, rbgIndex);
+    if(startPrb == MAX_NUM_RB)
+    {
+       DU_LOG("\nERROR  -->  SCH: No RBG is allocated for PDCCH in this Coreset");
+       return false;
+    }
+    /*[Step 2]: Adjust StartPrb based on CCEIndex and duration*/
+    startPrb = startPrb + ((cceIndex % pdcchInfo->cRSetRef->duration) * (pdcchInfo->nrOfPRBPerCce));
+    startSymbol = findSsStartSymbol(pdcchInfo->ssRef->mSymbolsWithinSlot);
+
+    /*numPrb will also get adjusted with duration*/
+    numPrb = (NUM_PRBS_PER_RBG * aggLvl) / pdcchInfo->cRSetRef->duration;
+    DU_LOG("\nDEBUG  -->  SCH: RBG found for cceIndex:%d, AggLvl:%d and SymbolDuration%d with StartPrb:%d, numPrb:%d",\
+            cceIndex, aggLvl, pdcchInfo->cRSetRef->duration, startPrb, numPrb);
+
+    ret = allocatePrbDl(cellCb, slotTime, startSymbol,\
+                         pdcchInfo->cRSetRef->duration, &startPrb, numPrb);
+    
+    if(ret == RFAILED)
+    {
+       DU_LOG("\nERROR -->  SCH: PRBs can't be allocated as they are unavailable");
+       return false;
+    }
+    return true;
+
+}
+
+/*
+ * @brief: Function to select particular UE based on validation of PDCCH allocation
+ *
+ *    Function: 
+ *    This function will have multiple layers of validation for PDCCH allocation 
+ *    based on CORESET and SearchSpace configuration and availability.
+ *
+ *    [Step 1]: Check if the slot is pdcch Slot or not based on SearchSpace's
+ *    monitoringSlotInfo.
+ *    [Step 2]: Check the CQI for this UE and decide upon which Agg Level has to
+ *    be used for this PDCCH transmission
+ *    [Step 3]: find the AggLevel for this CQI = base aggregation level
+ *    [Step 4]: NextLowerAggLvl will be the next lower aggLevel when PDCCH
+ *    allocation fails for base agg Level.
+ *    [Step 5]: For each candidate , calculate the CCE Index as per TS
+ *    38.213v15, Sec 10.1 and also check PRBs falling in that CCEIndex is free.
+ *    [Step 6]: If Step 5 fails, move to next candidate and if Candidate gets
+ *    exhausted then fallback to nextAggLevel. Because as we decrease aggLevel,
+ *    numberOfCCEReq decreases so chances of PDCCH allocation increases even
+ *    though lowerAggLevel will not guarantee transmission of PDCCH as per CQI
+ *    reported.(CQI less, AggiLvlRequried is More)
+ *
+ *    @params[IN]: SchUeCb and PdcchTime
+ *          [RETURN]: isPDCCHAllocted flag(true = UE can be selected as a
+ *          candidate )
+ * */
+bool schDlCandidateSelection(SchUeCb *ueCb, SlotTimingInfo pdcchTime, SchPdcchAllocInfo *pdcchAllocInfo)
+{
+    uint8_t cRSetIdx = 0, cceIndex = 0;
+    uint8_t cqi = 0, candIdx = 0;
+    uint8_t baseAggLvl = 0, nextLowerAggLvl = 0, numCandidates = 0;
+    SchPdcchInfo *pdcchInfo = NULLP;
+    uint32_t a = 0, b = 0;
+
+    for(cRSetIdx = 0; cRSetIdx < MAX_NUM_CRSET; cRSetIdx++)
+    {
+       pdcchInfo = &ueCb->pdcchInfo[cRSetIdx];
+       if(pdcchInfo->cRSetRef == NULLP)
+       {
+          DU_LOG("\nINFO   -->  SCH: Coreset is not availabe at Index:%d",cRSetIdx);
+          continue;
+       }
+       /*[Step 1]:*/
+       if(false == schPdcchSlotValidation(pdcchTime, pdcchInfo->ssRef, ueCb->cellCb->numSlots))
+       {
+          DU_LOG("\nINFO   -->  SCH: This slot is not valid for PDCCH in this CORESET:%d.",pdcchInfo->cRSetRef->cRSetId);
+          break;
+       }
+       /*[Step 2]:*/
+       /*TODO: CQI is reported in DL_CQI_IND which has to be processed and
+        * report has to be stored in ueCb.For now, HardCoding the value*/
+        cqi = 5;
+
+        /*[Step 3]: */
+        baseAggLvl = pdcchInfo->cqiIndxAggLvlMap[cqi];
+
+        /*[Step 4]:*/
+        nextLowerAggLvl = baseAggLvl;
+
+        /*Loop to traverse through each AggLvl from higher value of aggLevel to
+         * 1 AggLvl*/
+        do
+        {
+           /*Configured num of candidates for each Agg Level in search space */
+           numCandidates = extractNumOfCandForAggLvl(pdcchInfo->ssRef, nextLowerAggLvl); 
+           if(!numCandidates)
+           {
+             DU_LOG("\nINFO   --> SCH:  Num Of Candidates configured for this AggLvel:%d is ZERO",baseAggLvl);
+           }
+
+           /*[Step 5]:*/
+           for(candIdx= 0; candIdx < numCandidates; candIdx++)
+           {
+               /*Formula reference 3GPP TS 38.213v15, Sec 10.1, Variable 'a' and
+                * 'b' is used for segmenting the formulat for readability purpose
+                * */
+               a = pdcchInfo->y[pdcchTime.slot] + \
+                     ceil((candIdx * pdcchInfo->totalCceCount)/(baseAggLvl * numCandidates));
+               b = ceil(pdcchInfo->totalCceCount * baseAggLvl);
+               cceIndex = baseAggLvl * (a % b); 
+               if(schCheckPdcchAvail(ueCb->cellCb, pdcchTime, cceIndex, pdcchInfo,nextLowerAggLvl) == true)
+               {
+                  DU_LOG("\nINFO   -->  SCH: PDCCH allocation is successful at cceIndex:%d",cceIndex);
+                  pdcchAllocInfo->cRSetId = pdcchInfo->cRSetRef->cRSetId;
+                  pdcchAllocInfo->aggLvl = nextLowerAggLvl;
+                  pdcchAllocInfo->cceIndex = cceIndex;
+                  pdcchAllocInfo->ssId = pdcchInfo->ssRef->searchSpaceId;
+                  return true;  
+               }
+           }
+           nextLowerAggLvl = nextLowerAggLvl >> 1;
+        }while(nextLowerAggLvl > 0 && nextLowerAggLvl <= 16);
+    }
+    return false;
+}
 /**********************************************************************
   End of file
  **********************************************************************/