uint8_t ssbIdxSupported; /*!< Max SSB index */
SsbInfo ssbInfo[MAX_SSB_IDX]; /*!< SSB info */
bool sib1Pres; /*!< Flag to determine if SIB1 is present in this slot */
- uint8_t pdcchUe; /*!< UE for which PDCCH is scheduled in this slot */
- /*TODO: will remove the above parameter which is stopping multiUE allocation
- * for PDCCH*/
- uint32_t usedRbgForPdcch[FREQ_DOM_RSRC_SIZE]; /*Bitmap for used RBG during PDCCH allocation in this slot.*/
+ uint8_t pdcchUe; /*!< UE for which PDCCH Common is scheduled in this slot */
uint8_t pdschUe; /*!< UE for which PDSCH is scheduled in this slot */
RarAlloc *rarAlloc[MAX_NUM_UE]; /*!< RAR allocation per UE*/
DciInfo *ulGrant;
uint16_t *sharedPRB, uint16_t *reservedPRB, bool *isTxPayloadLenAdded, bool *srRcvd);
void updateBsrAndLcList(CmLListCp *lcLL, BsrInfo *bsrInfo, uint8_t status);
uint8_t fillUeCoresetAndSsInfo(SchUeCb *ue);
+bool schDlCandidateSelection(SchUeCb *ue, SlotTimingInfo slotTime);
/*Paging Functions*/
void schProcPagingCfg(SchCellCb *cell);
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)
+{
+ 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);
+ return true;
+ }
+ }
+ nextLowerAggLvl = nextLowerAggLvl >> 1;
+ }while(nextLowerAggLvl > 0 && nextLowerAggLvl <= 16);
+ }
+ return false;
+}
/**********************************************************************
End of file
**********************************************************************/
schAllocPucchResource(cell, pucchTime, crnti, ueCb, isRetx, *hqP);
- cell->schDlSlotInfo[pdcchTime.slot]->pdcchUe = ueId;
cell->schDlSlotInfo[pdschTime.slot]->pdschUe = ueId;
cell->schUlSlotInfo[pucchTime.slot]->pucchUe = ueId;
}
#endif
- if(cell->schDlSlotInfo[pdcchTime->slot]->pdcchUe != 0)
- {
- return false;
- }
-
if(dedMsg == true)
{
ueCb = &cell->ueCb[ueId-1];
k0K1InfoTbl = &ueCb->k0K1InfoTbl;
+ if(schDlCandidateSelection(ueCb, *pdcchTime) == false)
+ {
+ DU_LOG("\nDEBUG --> SCH: DL candidate Selection failed bcz PDCCH is unavailable for this slot");
+ return false;
+ }
}
else
{
*pdschStartSymbol = ueCb->ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].startSymbol;
*pdschSymblLen = ueCb->ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].symbolLength;
}
+ else
+ {
+ k0Val = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].k0;
+ *pdschStartSymbol = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].startSymbol;
+ *pdschSymblLen = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].lengthSymbol;
+ }
}
ADD_DELTA_TO_TIME((*pdcchTime), (*pdschTime), k0Val, cell->numSlots);
{
k1Val = ueCb->ueCfg.spCellCfg.servCellRecfg.initUlBwp.pucchCfg.dlDataToUlAck->dlDataToUlAckList[k1Index];
}
+ else
+ {
+ k1Val = defaultUlAckTbl[k1Index];
+ }
}
ADD_DELTA_TO_TIME((*pdschTime),(*pucchTime), k1Val, cell->numSlots);
#ifdef NR_TDD
BuildK0K1Table(ueCb->cellCb, &ueCb->k0K1InfoTbl, false, pdschCfg,\
ueCfg->spCellCfg.servCellCfg.initDlBwp.pdschCfg, dlDataToUlAck->dlDataToUlAckListCount,\
dlDataToUlAck->dlDataToUlAckList);
+ }
+ else
+ {
+ BuildK0K1Table(ueCb->cellCb, &ueCb->k0K1InfoTbl, false, pdschCfg,\
+ ueCfg->spCellCfg.servCellCfg.initDlBwp.pdschCfg, DEFAULT_UL_ACK_LIST_COUNT, defaultUlAckTbl);
+ }
ueCb->k0K1TblPrsnt = true;
BuildK2InfoTable(ueCb->cellCb, ueCfg->spCellCfg.servCellCfg.initUlBwp.puschCfg.timeDomRsrcAllocList,\
ueCfg->spCellCfg.servCellCfg.initUlBwp.puschCfg.numTimeDomRsrcAlloc,\
NULLP, &ueCb->k2InfoTbl);
ueCb->k2TblPrsnt = true;
- }
}
}
freeBlock->endPrb = MAX_NUM_RB-1;
addNodeToLList(&schDlSlotInfo->prbAlloc.freePrbBlockList, freeBlock, NULL);
}
- memset(schDlSlotInfo->usedRbgForPdcch, 0, (sizeof(uint32_t) * FREQ_DOM_RSRC_SIZE));
}
/**
return(MAX_SYMB_PER_SLOT);
}
+/*
+ * @brief: Function will extract the StartPrb as per the given RBGIndex
+ *
+ * Function: extractStartPrbForRBG
+ *
+ * This function will extract the StartPrb of a rbgIndex. This RbgIndex doesnt
+ * have direct mapping with index in FreqDomRsrc instead it is mapping with
+ * those rbg which is set(i.e. available for PDCCH)
+ *
+ * @param[in] uint8_t freqDomainRsrc[6] (As per Spec 38.331, ControlResourceSet.frequencyDomainResources)
+ * freqDomainRsrc[0] =RBG0 to RBG7
+ * freqDomainRsrc[1] =RBG8 to RBG15
+ * ...
+ * freqDomainRsrc[5] =RBG40 to RBG47
+ * (Every RBG has 6 PRBs)
+ *
+ * uint8_t rbgIndex
+ *
+ *
+ * [return]: startPrb of that rbgIndex
+ * */
+uint16_t extractStartPrbForRBG(uint8_t *freqDomainRsrc, uint8_t rbgIndex)
+{
+ uint8_t freqIdx = 0, idx = 0;
+ uint8_t count = 0, bitPos = 0;
+ uint8_t totalPrbPerFreqIdx = NUM_PRBS_PER_RBG * 8; /*8 = no. of Bits in uint8_t*/
+ uint16_t startPrb = MAX_NUM_RB;
+
+ for(freqIdx = 0; freqIdx < FREQ_DOM_RSRC_SIZE; freqIdx++)
+ {
+ if(freqDomainRsrc[freqIdx] & 0xFF)
+ {
+ /*Tracking from the 7th Bit because in FreqDomRsrc , lowestPRB is
+ * stored in MSB and so on*/
+ idx = 128;
+ bitPos = 0;
+ while(idx)
+ {
+ if(freqDomainRsrc[freqIdx] & idx)
+ {
+ if(count == rbgIndex)
+ {
+ startPrb = (totalPrbPerFreqIdx * freqIdx) + (bitPos * NUM_PRBS_PER_RBG);
+ return startPrb;
+ }
+ count++;
+ }
+ bitPos++;
+ idx = idx >> 1;
+ }
+ }
+ }
+ return startPrb;
+}
/**
* @brief Function to count number of RBG from Coreset's FreqDomainResource
*
**/
uint8_t countRBGFrmCoresetFreqRsrc(uint8_t *freqDomainRsrc)
{
- uint8_t freqIdx = 0, idx = 1;
+ uint8_t freqIdx = 0, idx = 0;
uint8_t count = 0;
for(freqIdx = 0; freqIdx < FREQ_DOM_RSRC_SIZE; freqIdx++)
if(freqDomainRsrc[freqIdx] & 0xFF)
{
idx = 1;
- count = 0;
while(idx)
{
if(freqDomainRsrc[freqIdx] & idx)
}
return ROK;
}
+
+/*
+ * @brief : Function to convert SlotPeriodicity to Value
+ *
+ * Function: schConvertSlotPeriodicityEnumToValue
+ *
+ * @param[IN]: SchMSlotPeriodicity enum
+ * [return]: slotOffsetVal
+ * */
+uint16_t schConvertSlotPeriodicityEnumToValue(SchMSlotPeriodicity slotPeriod)
+{
+ uint16_t slotPeriodVal = 0;
+
+ switch(slotPeriod)
+ {
+ case SLOT_PERIODICITY_SL_1:
+ {
+ slotPeriodVal = 1;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_2:
+ {
+ slotPeriodVal = 2;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_4:
+ {
+ slotPeriodVal = 4;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_5:
+ {
+ slotPeriodVal = 5;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_8:
+ {
+ slotPeriodVal = 8;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_10:
+ {
+ slotPeriodVal = 10;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_16:
+ {
+ slotPeriodVal = 16;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_20:
+ {
+ slotPeriodVal = 20;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_40:
+ {
+ slotPeriodVal = 40;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_80:
+ {
+ slotPeriodVal = 80;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_160:
+ {
+ slotPeriodVal = 160;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_320:
+ {
+ slotPeriodVal = 320;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_640:
+ {
+ slotPeriodVal = 640;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_1280:
+ {
+ slotPeriodVal = 1280;
+ break;
+ }
+ case SLOT_PERIODICITY_SL_2560:
+ {
+ slotPeriodVal = 2560;
+ break;
+ }
+ default:
+ {
+ slotPeriodVal = 0;
+ break;
+ }
+ }
+ return slotPeriodVal;
+}
+
+/*
+ * @brief: Function to extract the numCandidates from aggLevel.
+ *
+ * Function: extractNumOfCandForAggLvl
+ *
+ * @params[IN]: SearchSpace, aggLevel
+ * [RETURN]: numCandidates.
+ * */
+uint8_t extractNumOfCandForAggLvl(SchSearchSpace *searchSpace, uint8_t aggLvl)
+{
+ uint8_t numCand = 0;
+
+ switch(aggLvl)
+ {
+ case 1:
+ {
+ numCand = searchSpace->numCandidatesAggLevel1;
+ break;
+ }
+ case 2:
+ {
+ numCand = searchSpace->numCandidatesAggLevel2;
+ break;
+ }
+ case 4:
+ {
+ numCand = searchSpace->numCandidatesAggLevel4;
+ break;
+ }
+ case 8:
+ {
+ numCand = searchSpace->numCandidatesAggLevel8;
+ break;
+ }
+ case 16:
+ {
+ numCand = searchSpace->numCandidatesAggLevel16;
+ break;
+ }
+ default:
+ {
+ numCand = 0;
+ }
+ /*AGGREGATION_LEVEL_N8 enum Value is 7 thus hardcoding the correct Value
+ * (8)*/
+ if(numCand == AGGREGATION_LEVEL_N8)
+ {
+ numCand = 8;
+ }
+ }
+ return numCand;
+}
/**********************************************************************
End of file
**********************************************************************/
_pst.selector = ODU_SELECTOR_TC; \
}
+
/* Table array declarations */
int8_t coresetIdxTable[MAX_CORESET_INDEX][4];
int8_t searchSpaceIdxTable[MAX_SEARCH_SPACE_INDEX][4];
uint8_t findSsStartSymbol(uint8_t *mSymbolsWithinSlot);
void fillCqiAggLvlMapping(SchPdcchInfo *pdcchInfo);
uint8_t schUpdValY(SchUeCb *ueCb, SchPdcchInfo *pdcchInfo);
+uint16_t extractStartPrbForRBG(uint8_t *freqDomaRsrc, uint8_t rbgIndex);
+uint16_t schConvertSlotPeriodicityEnumToValue(SchMSlotPeriodicity slotPeriod);
+uint8_t extractNumOfCandForAggLvl(SchSearchSpace *searchSpace, uint8_t aggLvl);
#if 0
/*Will be enabled for debugging*/
void printLcLL(CmLListCp *lcLL);