void EnhancedUplinkPacketScheduler::RBsAllocation () { /* This is an implementation of an algorithm based on first maximum expansion algorithm reported in * L. Temiño, G. Berardinelli, S. Frattasi, and P.E. Mogensen, * "Channel-aware scheduling algorithms for SC-FDMA in LTE uplink", in Proc. PIMRC 2008 * The main difference is that here we have a given number of RB's to allocate to the UE * based on its pending queue status whereas the original attempts to allocate till another * UE has a better channel response */ #ifdef SCHEDULER_DEBUG std::cout << " ---- UL RBs Allocation"; #endif UsersToSchedule *users = GetUsersToSchedule (); UserToSchedule* scheduledUser; int nbOfRBs = GetMacEntity ()->GetDevice ()->GetPhy ()->GetBandwidthManager ()->GetUlSubChannels ().size (); int availableRBs; // No of RB's not allocated int unallocatedUsers; // No of users who remain unallocated int selectedUser; // user to be selected for allocation int selectedPRB; // PRB to be selected for allocation double bestMetric; // best metric to identify user/RB combination int left, right; // index of left and left PRB's to check bool Allocated[nbOfRBs]; bool allocationMade; double metrics[nbOfRBs][users->size ()]; int requiredPRBs[users->size ()]; //Some initialization availableRBs = nbOfRBs; unallocatedUsers = users->size (); for(int i=0; i < nbOfRBs; i++) Allocated[i] = false; //create a matrix of flow metrics for (int i = 0; i < nbOfRBs; i++) { for (int j = 0; j < users->size (); j++) { metrics[i][j] = ComputeSchedulingMetric (users->at (j), i); } } //create number of required PRB's per scheduled users for(int j=0; j < users->size(); j++) { scheduledUser = users->at(j); #ifdef SCHEDULER_DEBUG cout << "\n" << "User " << j; // << "CQI Vector"; #endif std::vector<double> sinrs; for (std::vector<int>::iterator c = scheduledUser->m_channelContition.begin (); c != scheduledUser->m_channelContition.end (); c++) { //cout << *c <<" "; sinrs.push_back (GetMacEntity ()->GetAmcModule ()->GetSinrFromCQI (*c)); } double effectiveSinr = GetEesmEffectiveSinr (sinrs); int mcs = GetMacEntity ()->GetAmcModule ()->GetMCSFromCQI ( GetMacEntity ()->GetAmcModule ()->GetCQIFromSinr (effectiveSinr)); scheduledUser->m_selectedMCS = mcs; requiredPRBs[j] = (floor) (scheduledUser->m_dataToTransmit / (GetMacEntity ()->GetAmcModule ()->GetTBSizeFromMCS (mcs, 1) / 8)); #ifdef SCHEDULER_DEBUG cout << " EffSINR = " << effectiveSinr << " MCS = " << mcs << "\n"; #endif } #ifdef SCHEDULER_DEBUG //std::cout << ", available RBs " << nbOfRBs << ", users " << users->size () << std::endl; for (int ii = 0; ii < users->size (); ii++) { std::cout << "Metrics for user " << users->at (ii)->m_userToSchedule->GetIDNetworkNode () << "\n"; for (int jj = 0; jj < nbOfRBs; jj++) { //std::cout << setw(3) << metrics[jj][ii]/1000 << " "; printf("%3d ", (int) (metrics[jj][ii]/1000.0)); } std::cout << std::endl; } #endif //RBs allocation while(availableRBs > 0 && unallocatedUsers > 0) // { // First step: find the best user-RB combo selectedPRB = -1; selectedUser = -1; bestMetric = (double) (-(1<<30)); for(int i=0; i < nbOfRBs; i++) { if (!Allocated[i]){ // check only unallocated PRB's for(int j=0; j < users->size (); j++) { if ( users->at (j)->m_listOfAllocatedRBs.size() == 0 && requiredPRBs[j] > 0) //only unallocated users requesting some RB's if (bestMetric < metrics[i][j]){ selectedPRB = i; selectedUser = j; bestMetric = metrics[i][j]; } } } } // Now start allocating for the selected user at the selected PRB the required blocks // using how many PRB's are needed for the user if (selectedUser != -1) { scheduledUser = users->at(selectedUser); scheduledUser->m_listOfAllocatedRBs.push_back (selectedPRB); Allocated[selectedPRB] = true; left = selectedPRB - 1; right = selectedPRB + 1; availableRBs--; unallocatedUsers--; allocationMade = true; for(int i = 1; i < requiredPRBs[selectedUser] && availableRBs > 0 && allocationMade; i++ ) { // search right and left of initial allocation allocationMade = false; if (left >=0 && Allocated[left] && right < nbOfRBs && Allocated[right]) break; // nothing is available, since we need to have contiguous allocation if ( (right < nbOfRBs) && (! Allocated[right]) && ( ((left >=0) && (metrics[right][selectedUser] >= metrics[left][selectedUser])) // right is better than left || (left < 0) || Allocated[left]// OR no more left ) ) { //Allocate PRB at right to the user Allocated[right] = true; scheduledUser->m_listOfAllocatedRBs.push_back (right); right++; allocationMade = true; availableRBs--; } else if ( (left >=0) && (! Allocated[left]) && ( ((right < nbOfRBs) && (metrics[left][selectedUser] > metrics[right][selectedUser])) //left better than right || (right >= nbOfRBs) || Allocated[right]// OR no more right ) ) { //Allocate PRB at left to the user Allocated[left] = true; scheduledUser->m_listOfAllocatedRBs.push_back (left); left--; allocationMade = true; availableRBs--; } } // end of for if (allocationMade){ scheduledUser->m_transmittedData = GetMacEntity ()->GetAmcModule ()-> GetTBSizeFromMCS (scheduledUser->m_selectedMCS, scheduledUser->m_listOfAllocatedRBs.size()) / 8; #ifdef SCHEDULER_DEBUG printf("Scheduled User = %d mcs = %d Required RB's = %d Allocated RB's= %d\n", scheduledUser->m_userToSchedule->GetIDNetworkNode(), scheduledUser->m_selectedMCS, requiredPRBs[selectedUser], scheduledUser->m_listOfAllocatedRBs.size() ); for(int i=0; i<scheduledUser->m_listOfAllocatedRBs.size(); i++) printf("%d ", scheduledUser->m_listOfAllocatedRBs.at(i)); printf("\n------------------\n"); #endif } } else { // nothing to do exit the allocation loop break; } } //while }
void DownlinkPacketScheduler::RBsAllocation () { #ifdef SCHEDULER_DEBUG std::cout << " ---- DownlinkPacketScheduler::RBsAllocation"; #endif FlowsToSchedule* flows = GetFlowsToSchedule (); int nbOfRBs = GetMacEntity ()->GetDevice ()->GetPhy ()->GetBandwidthManager ()->GetDlSubChannels ().size (); //create a matrix of flow metrics double metrics[nbOfRBs][flows->size ()]; for (int i = 0; i < nbOfRBs; i++) { for (int j = 0; j < flows->size (); j++) { metrics[i][j] = ComputeSchedulingMetric (flows->at (j)->GetBearer (), flows->at (j)->GetSpectralEfficiency ().at (i), i); } } #ifdef SCHEDULER_DEBUG std::cout << ", available RBs " << nbOfRBs << ", flows " << flows->size () << std::endl; for (int ii = 0; ii < flows->size (); ii++) { std::cout << "\t metrics for flow " << flows->at (ii)->GetBearer ()->GetApplication ()->GetApplicationID () << ":"; for (int jj = 0; jj < nbOfRBs; jj++) { std::cout << " " << metrics[jj][ii]; } std::cout << std::endl; } #endif AMCModule *amc = GetMacEntity ()->GetAmcModule (); double l_dAllocatedRBCounter = 0; int l_iNumberOfUsers = ((ENodeB*)this->GetMacEntity()->GetDevice())->GetNbOfUserEquipmentRecords(); bool * l_bFlowScheduled = new bool[flows->size ()]; int l_iScheduledFlows = 0; std::vector<double> * l_bFlowScheduledSINR = new std::vector<double>[flows->size ()]; for (int k = 0; k < flows->size (); k++) l_bFlowScheduled[k] = false; //RBs allocation for (int s = 0; s < nbOfRBs; s++) { if (l_iScheduledFlows == flows->size ()) break; double targetMetric = 0; bool RBIsAllocated = false; FlowToSchedule* scheduledFlow; int l_iScheduledFlowIndex = 0; for (int k = 0; k < flows->size (); k++) { if (metrics[s][k] > targetMetric && !l_bFlowScheduled[k] && flows->at (k)->GetDataToTransmit() >0 ) { targetMetric = metrics[s][k]; RBIsAllocated = true; scheduledFlow = flows->at (k); l_iScheduledFlowIndex = k; } } if (RBIsAllocated) { l_dAllocatedRBCounter++; scheduledFlow->GetListOfAllocatedRBs()->push_back (s); // the s RB has been allocated to that flow! #ifdef SCHEDULER_DEBUG std::cout << "\t *** RB " << s << " assigned to the " " flow " << scheduledFlow->GetBearer ()->GetApplication ()->GetApplicationID () << std::endl; #endif double sinr = amc->GetSinrFromCQI (scheduledFlow->GetCqiFeedbacks ().at (s)); l_bFlowScheduledSINR[l_iScheduledFlowIndex].push_back(sinr); double effectiveSinr = GetEesmEffectiveSinr (l_bFlowScheduledSINR[l_iScheduledFlowIndex]); int mcs = amc->GetMCSFromCQI (amc->GetCQIFromSinr (effectiveSinr)); int transportBlockSize = amc->GetTBSizeFromMCS (mcs, scheduledFlow->GetListOfAllocatedRBs ()->size ()); if (transportBlockSize >= scheduledFlow->GetDataToTransmit() * 8) { l_bFlowScheduled[l_iScheduledFlowIndex] = true; l_iScheduledFlows++; } } } delete [] l_bFlowScheduled; delete [] l_bFlowScheduledSINR; //Finalize the allocation PdcchMapIdealControlMessage *pdcchMsg = new PdcchMapIdealControlMessage (); for (FlowsToSchedule::iterator it = flows->begin (); it != flows->end (); it++) { FlowToSchedule *flow = (*it); if (flow->GetListOfAllocatedRBs ()->size () > 0) { //this flow has been scheduled std::vector<double> estimatedSinrValues; for (int rb = 0; rb < flow->GetListOfAllocatedRBs ()->size (); rb++ ) { double sinr = amc->GetSinrFromCQI ( flow->GetCqiFeedbacks ().at (flow->GetListOfAllocatedRBs ()->at (rb))); estimatedSinrValues.push_back (sinr); } //compute the effective sinr double effectiveSinr = GetEesmEffectiveSinr (estimatedSinrValues); //get the MCS for transmission int mcs = amc->GetMCSFromCQI (amc->GetCQIFromSinr (effectiveSinr)); //define the amount of bytes to transmit //int transportBlockSize = amc->GetTBSizeFromMCS (mcs); int transportBlockSize = amc->GetTBSizeFromMCS (mcs, flow->GetListOfAllocatedRBs ()->size ()); double bitsToTransmit = transportBlockSize; flow->UpdateAllocatedBits (bitsToTransmit); #ifdef SCHEDULER_DEBUG std::cout << "\t\t --> flow " << flow->GetBearer ()->GetApplication ()->GetApplicationID () << " has been scheduled: " << "\n\t\t\t nb of RBs " << flow->GetListOfAllocatedRBs ()->size () << "\n\t\t\t effectiveSinr " << effectiveSinr << "\n\t\t\t tbs " << transportBlockSize << "\n\t\t\t bitsToTransmit " << bitsToTransmit << std::endl; #endif //create PDCCH messages for (int rb = 0; rb < flow->GetListOfAllocatedRBs ()->size (); rb++ ) { pdcchMsg->AddNewRecord (PdcchMapIdealControlMessage::DOWNLINK, flow->GetListOfAllocatedRBs ()->at (rb), flow->GetBearer ()->GetDestination (), mcs); } } } if (pdcchMsg->GetMessage()->size () > 0) { GetMacEntity ()->GetDevice ()->GetPhy ()->SendIdealControlMessage (pdcchMsg); } delete pdcchMsg; }