![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /******************************************************************************* 00002 * This file is part of openWNS (open Wireless Network Simulator) 00003 * _____________________________________________________________________________ 00004 * 00005 * Copyright (C) 2004-2007 00006 * Chair of Communication Networks (ComNets) 00007 * Kopernikusstr. 5, D-52074 Aachen, Germany 00008 * phone: ++49-241-80-27910, 00009 * fax: ++49-241-80-22242 00010 * email: info@openwns.org 00011 * www: http://www.openwns.org 00012 * _____________________________________________________________________________ 00013 * 00014 * openWNS is free software; you can redistribute it and/or modify it under the 00015 * terms of the GNU Lesser General Public License version 2 as published by the 00016 * Free Software Foundation; 00017 * 00018 * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY 00019 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00020 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00021 * details. 00022 * 00023 * You should have received a copy of the GNU Lesser General Public License 00024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00025 * 00026 ******************************************************************************/ 00027 00028 #include <WNS/scheduler/harq/HARQ.hpp> 00029 #include <WNS/Exception.hpp> 00030 #include <boost/bind.hpp> 00031 #include <boost/foreach.hpp> 00032 00033 using namespace wns::scheduler::harq; 00034 00035 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00036 HARQ, 00037 HARQInterface, 00038 "harq", 00039 wns::PyConfigViewCreator); 00040 00041 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00042 UniformRandomDecoder, 00043 IDecoder, 00044 "UniformRandomDecoder", 00045 wns::PyConfigViewCreator); 00046 00047 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00048 ChaseCombiningDecoder, 00049 IDecoder, 00050 "ChaseCombiningDecoder", 00051 wns::PyConfigViewCreator); 00052 00053 UniformRandomDecoder::UniformRandomDecoder(const wns::pyconfig::View& config): 00054 dis_(new wns::distribution::StandardUniform()), 00055 initialPER_(config.get<double>("initialPER")), 00056 rolloffFactor_(config.get<double>("rolloffFactor")), 00057 logger_(config.get("logger")) 00058 { 00059 } 00060 00061 UniformRandomDecoder::UniformRandomDecoder(const UniformRandomDecoder& other): 00062 dis_(new wns::distribution::StandardUniform()), 00063 initialPER_(other.initialPER_), 00064 rolloffFactor_(other.rolloffFactor_), 00065 logger_(other.logger_) 00066 { 00067 } 00068 00069 bool 00070 UniformRandomDecoder::canDecode(SoftCombiningContainer input) 00071 { 00072 int numTransmissions = 0; 00073 00074 std::list<int> positions = input.getAvailablePosInTB(); 00075 00076 assure(positions.size() > 0, "Nothing to decode"); 00077 00078 for (int ii=0; ii < input.getNumRVs(); ++ii) 00079 { 00080 numTransmissions += input.getEntriesForRV(positions.front(), ii).size(); 00081 } 00082 00083 double threshold = pow(initialPER_, numTransmissions * rolloffFactor_); 00084 00085 //MESSAGE_BEGIN(NORMAL, logger_, m, ""); 00086 //m << "Effective PER is " << threshold; 00087 //MESSAGE_END(); 00088 00089 if ((*dis_)() > threshold) 00090 { 00091 return true; 00092 } 00093 return false; 00094 } 00095 00096 ChaseCombiningDecoder::ChaseCombiningDecoder(const wns::pyconfig::View& config): 00097 dis_(new wns::distribution::StandardUniform()), 00098 logger_(config.get("logger")), 00099 effSINRCC_("winprost.effSINR") 00100 { 00101 } 00102 00103 ChaseCombiningDecoder::ChaseCombiningDecoder(const ChaseCombiningDecoder& other): 00104 dis_(new wns::distribution::StandardUniform()), 00105 logger_(other.logger_), 00106 effSINRCC_("winprost.effSINR") 00107 { 00108 } 00109 00110 bool 00111 ChaseCombiningDecoder::canDecode(SoftCombiningContainer input) 00112 { 00113 // input contains softcombining containers including multiple subchannels 00114 00115 // Calculate effective MIB 00116 00117 // According to IEEE 802.16m-08/004r5 (PMD) pp. 91 Chase Combinig can be modeled as 00118 // follows. Sum up all SINR values in the linear domain (power, not dB) for one symbol. From that value 00119 // determine the Sum Mutual Information per bit (MIB). Calculate the average MIB of all symbols. 00120 // From this value the PER can be detected according to the coding scheme 00121 // Here we do not work on symbols but on subchannels. 00122 00123 double mib = 0; 00124 int totalSize = 0; 00125 int numSC = 0; 00126 00127 00128 std::list<int> positions = input.getAvailablePosInTB(); 00129 00130 assure(positions.size() > 0, "Nothing to decode"); 00131 00132 assure(input.getEntriesForRV(positions.front(),0).size() > 0, "Nothing to decode"); 00133 00134 wns::service::phy::phymode::PhyModeInterfacePtr pm = input.getEntriesForRV(positions.front(),0).front().measurement_->getPhyMode(); 00135 00136 MESSAGE_SINGLE(NORMAL, logger_, "Decoding a TB spanning " << positions.size() << " subchannels"); 00137 00138 std::list<int>::iterator it; 00139 00140 for (it=positions.begin(); it!=positions.end(); ++it) 00141 { 00142 numSC++; 00143 00144 for (int ii=1; ii < input.getNumRVs(); ++ii) 00145 { 00146 assure(input.getEntriesForRV(*it, ii).size() == 0, "ChaseCombining expects only RV 0 to be used, but RV=" << ii << " is used, too."); 00147 } 00148 00149 std::list<SchedulingTimeSlotInfo> sis = input.getEntriesForRV(*it, 0); 00150 assure(sis.size() > 0, "Chase combining has no receptions for RV 0."); 00151 00152 std::list<SchedulingTimeSlotInfo>::iterator it; 00153 00154 assure( (*pm)==(*sis.front().measurement_->getPhyMode()), "Must have the same phy modes on all SCs"); 00155 00156 double sumSINR = 0.0; 00157 // For all retransmissions: 00158 for(it = sis.begin(); it != sis.end(); ++it) 00159 { 00160 sumSINR += it->measurement_->getSINR().get_factor(); 00161 } 00162 00163 totalSize += sis.front().timeSlot_->getNetBlockSizeInBits(); // (net,netto, i.e. without code/redundancy bits) 00164 mib += sis.front().measurement_->getPhyMode()->getSINR2MIB(wns::Ratio::from_factor(sumSINR)); 00165 } 00166 00167 // Mean MIB for whole TB 00168 mib = mib/numSC; 00169 00170 double per = pm->getMI2PER(mib, totalSize); // MIB not MI is expected here 00171 00172 MESSAGE_BEGIN(NORMAL, logger_, m, "canDecode: PhyMode=" << *pm); 00173 m << ", Average MIB=" << mib; 00174 m << ", bits=" << totalSize; 00175 m << " => per=" << per; 00176 MESSAGE_END(); 00177 00178 wns::scheduler::UserID userID = input.getEntriesForRV(positions.front(),0).front().timeSlot_->physicalResources[0].getSourceUserIDOfScheduledCompounds(); 00179 unsigned int nodeID = userID.getNodeID(); 00180 00181 if ((*dis_)() > per) 00182 { 00183 MESSAGE_SINGLE(NORMAL, logger_, "Decode success"); 00184 00185 effSINRCC_.put(pm->getMIB2SINR(mib).get_dB(), boost::make_tuple("nodeID",nodeID, "decoded", 1)); 00186 return true; 00187 } 00188 MESSAGE_SINGLE(NORMAL, logger_, "Decode failed"); 00189 effSINRCC_.put(pm->getMIB2SINR(mib).get_dB(), boost::make_tuple("nodeID",nodeID, "decoded", 0)); 00190 return false; 00191 } 00192 00193 HARQ::HARQ(const wns::pyconfig::View& config): 00194 numSenderProcesses_(config.get<int>("numSenderProcesses")), 00195 numReceiverProcesses_(config.get<int>("numReceiverProcesses")), 00196 numRVs_(config.get<int>("numRVs")), 00197 logger_(config.get("logger")), 00198 retransmissionLimit_(config.get<int>("retransmissionLimit")), 00199 harqEntityPrototype_(new HARQEntity(config.get("harqEntity"), numSenderProcesses_, numReceiverProcesses_, numRVs_, retransmissionLimit_, logger_)), 00200 numRetransmissionsProbeCC("scheduler.harq.retransmissions") 00201 { 00202 } 00203 00204 HARQ::~HARQ() 00205 { 00206 } 00207 00208 HARQEntity* 00209 HARQ::findEntity(wns::scheduler::UserID userID) 00210 { 00211 if (!harqEntities_.knows(userID)) 00212 { 00213 MESSAGE_SINGLE(NORMAL, logger_, "Creating new HARQEntity for peer UserID=" << userID.getName() ); 00214 HARQEntity* he = wns::clone(harqEntityPrototype_); 00215 harqEntities_.insert(userID, he); 00216 00217 return he; 00218 } 00219 00220 return harqEntities_.find(userID); 00221 } 00222 00223 void 00224 HARQ::storeSchedulingTimeSlot(long int transportBlockID, const wns::scheduler::SchedulingTimeSlotPtr& resourceBlock) 00225 { 00226 assure(resourceBlock->physicalResources[0].hasScheduledCompounds(), "No resources in RB"); 00227 00228 int subChannelIndex = resourceBlock->subChannelIndex; 00229 int timeSlotIndex = resourceBlock->timeSlotIndex; 00230 00231 if (!resourceBlock->isHARQEnabled()) 00232 { 00233 MESSAGE_SINGLE(NORMAL, logger_, "storeSchedulingTimeSlot("<<subChannelIndex<<"."<<timeSlotIndex<<"): HARQ is disabled. Skipping."); 00234 MESSAGE_SINGLE(NORMAL, logger_, resourceBlock->toString()); 00235 return; 00236 } 00237 else if (resourceBlock->isEmpty()) 00238 { 00239 MESSAGE_SINGLE(NORMAL, logger_, "storeSchedulingTimeSlot("<<subChannelIndex<<"."<<timeSlotIndex<<"): time slot is empty"); 00240 MESSAGE_SINGLE(NORMAL, logger_, resourceBlock->toString()); 00241 return; 00242 } 00243 else if (!resourceBlock->harq.NDI) 00244 { 00245 MESSAGE_SINGLE(NORMAL, logger_, "storeSchedulingTimeSlot("<<subChannelIndex<<"."<<timeSlotIndex<<"): Found a retransmission. Skipping."); 00246 MESSAGE_SINGLE(NORMAL, logger_, resourceBlock->toString()); 00247 return; 00248 } 00249 else 00250 { 00251 // The destination user is in the scheduled compound 00252 // The scheduling time slot does not have the right user, 00253 // because of the way how the wns::scheduler works. 00254 // Certainly, this could be done better, works for now 00255 00259 wns::scheduler::UserID destination = resourceBlock->physicalResources[0].getUserIDOfScheduledCompounds(); 00260 00261 //MESSAGE_SINGLE(NORMAL, logger_, "storeSchedulingTimeSlot("<<subChannelIndex<<"."<<timeSlotIndex<<")"); 00262 MESSAGE_SINGLE(NORMAL, logger_, "storeSchedulingTimeSlot("<<subChannelIndex<<"."<<timeSlotIndex<<")" 00263 <<" for "<< destination.getName()); 00264 MESSAGE_SINGLE(NORMAL, logger_, resourceBlock->toString()); 00265 } 00266 00267 // at this point we have a brand new transmission which we must take care of... 00268 // this is the userID seen from here (the sending peer): 00269 wns::scheduler::UserID userID = resourceBlock->physicalResources[0].getUserIDOfScheduledCompounds(); 00270 00271 HARQEntity* entity = this->findEntity(userID); 00272 00273 assure(entity->hasCapacity(transportBlockID), "The HARQ Entity for peer UserID=" << userID.getName() << " does not have anymore capacity!"); 00274 00275 // now store the SchedulingTimeSlotPtr 00279 entity->newTransmission(transportBlockID, resourceBlock); 00280 } 00281 00282 void 00283 HARQ::onTimeSlotReceived(const wns::scheduler::SchedulingTimeSlotPtr& resourceBlock, 00284 HARQInterface::TimeSlotInfo info) 00285 { 00286 wns::scheduler::UserID userID = resourceBlock->physicalResources[0].getSourceUserIDOfScheduledCompounds(); 00287 00288 00289 MESSAGE_SINGLE(NORMAL, logger_, "onTimeSlotReceived(resource=" 00290 << resourceBlock->subChannelIndex << "." 00291 << resourceBlock->timeSlotIndex <<")" 00292 << " for "<< userID.getName()); 00293 00294 resourceBlock->consistencyCheck(); 00295 00296 HARQEntity* entity = this->findEntity(userID); 00300 entity->onTimeSlotReceived(resourceBlock, info); 00301 00302 MESSAGE_SINGLE(NORMAL, logger_, "onTimeSlotReceived(resource="<<resourceBlock->subChannelIndex<<"."<<resourceBlock->timeSlotIndex<<")" 00303 <<" for "<<userID.getName()<< " TBID " << resourceBlock->harq.transportBlockID << ")"); 00304 } 00305 00306 HARQInterface::DecodeStatusContainer 00307 HARQ::decode() 00308 { 00309 HARQInterface::DecodeStatusContainer tmp; 00310 00311 00312 // Join all others 00313 for(HARQEntityContainer::const_iterator it=harqEntities_.begin(); it!=harqEntities_.end(); ++it) 00314 { 00315 HARQInterface::DecodeStatusContainer perEntity; 00316 perEntity = it->second->decode(); 00317 00318 for (HARQInterface::DecodeStatusContainer::iterator it2=perEntity.begin(); it2!=perEntity.end(); ++it2) 00319 { 00320 if (it2->first->harq.successfullyDecoded || it2->first->harq.retryCounter >= retransmissionLimit_ ) { 00321 wns::scheduler::UserID userID = it2->first->physicalResources[0].getSourceUserIDOfScheduledCompounds(); 00322 unsigned int nodeID = userID.getNodeID(); 00323 numRetransmissionsProbeCC.put(it2->first->harq.retryCounter, boost::make_tuple("nodeID",nodeID)); 00324 } 00325 tmp.push_back(*it2); 00326 } 00327 } 00328 00329 return tmp; 00330 } 00331 00332 wns::scheduler::UserSet 00333 HARQ::getUsersWithRetransmissions() const 00334 { 00335 wns::scheduler::UserSet users; 00336 00337 for (HARQEntityContainer::const_iterator it = harqEntities_.begin(); 00338 it != harqEntities_.end(); 00339 ++it) 00340 { // foreach user 00341 if (it->second->hasRetransmissions()) 00342 { 00343 users.insert(it->first); 00344 } 00345 } 00346 return users; 00347 } 00348 00349 std::list<int> 00350 HARQ::getProcessesWithRetransmissions(wns::scheduler::UserID peer) const 00351 { 00352 if(harqEntities_.knows(peer)) 00353 { 00354 return harqEntities_.find(peer)->getProcessesWithRetransmissions(); 00355 } 00356 else 00357 { 00358 std::list<int> empty; 00359 return empty; 00360 } 00361 } 00362 00363 int 00364 HARQ::getNumberOfRetransmissions(wns::scheduler::UserID user, int processID) 00365 { 00366 HARQEntity* he = findEntity(user); 00367 return he->getNumberOfRetransmissions(processID); 00368 } 00369 00370 00371 wns::scheduler::SchedulingTimeSlotPtr 00372 HARQ::getNextRetransmission(wns::scheduler::UserID user, int processID) 00373 { 00374 if (harqEntities_.knows(user)) 00375 { 00376 HARQEntity* he = findEntity(user); 00377 00378 wns::scheduler::SchedulingTimeSlotPtr r; 00379 r = he->getNextRetransmission(processID); 00380 00381 if (r != NULL) 00382 { 00383 r->consistencyCheck(); 00384 return r; 00385 } 00386 } 00387 else 00388 { 00389 throw wns::Exception("No user by that name in getNextRetransmission " + user.getName()); 00390 } 00391 00392 return wns::scheduler::SchedulingTimeSlotPtr(); // empty 00393 } 00394 00395 wns::scheduler::SchedulingTimeSlotPtr 00396 HARQ::peekNextRetransmission(wns::scheduler::UserID user, int processID) const 00397 { 00398 if (harqEntities_.knows(user)) 00399 { 00400 wns::scheduler::SchedulingTimeSlotPtr r; 00401 r = harqEntities_.find(user)->peekNextRetransmission(processID); 00402 00403 if (r != NULL) 00404 { 00405 r->consistencyCheck(); 00406 return r; 00407 } 00408 } 00409 return wns::scheduler::SchedulingTimeSlotPtr(); // empty 00410 } 00411 00412 void 00413 HARQ::setDownlinkHARQ(HARQInterface* downlinkHARQ) 00414 { 00415 assure(false, "You tried to set a downlinkHARQ in the downlink HARQ dude."); 00416 } 00417 00418 wns::scheduler::UserSet 00419 HARQ::getPeersWithPendingRetransmissions() const 00420 { 00421 wns::scheduler::UserSet u; 00422 00423 for (HARQEntityContainer::const_iterator it = harqEntities_.begin(); 00424 it != harqEntities_.end(); 00425 ++it) 00426 { // foreach user 00427 if (it->second->getPeerProcessesWithRetransmissions().size() > 0) 00428 { 00429 u.insert(it->first); 00430 } 00431 } 00432 return u; 00433 } 00434 00435 std::list<int> 00436 HARQ::getPeerProcessesWithRetransmissions(wns::scheduler::UserID peer) const 00437 { 00438 if(harqEntities_.knows(peer)) 00439 { 00440 return harqEntities_.find(peer)->getPeerProcessesWithRetransmissions(); 00441 } 00442 else 00443 { 00444 std::list<int> empty; 00445 return empty; 00446 } 00447 } 00448 00449 int 00450 HARQ::getNumberOfPeerRetransmissions(wns::scheduler::UserID peer, int processID) const 00451 { 00452 if(harqEntities_.knows(peer)) 00453 { 00454 return harqEntities_.find(peer)->getNumberOfPeerRetransmissions(processID); 00455 } 00456 00457 return 0; 00458 } 00459 00460 bool 00461 HARQ::hasFreeSenderProcess(wns::scheduler::UserID peer) 00462 { 00463 if(harqEntities_.knows(peer)) 00464 { 00465 return harqEntities_.find(peer)->hasCapacity(0); 00466 } 00467 return true; 00468 } 00469 00470 bool 00471 HARQ::hasFreeReceiverProcess(wns::scheduler::UserID peer) 00472 { 00473 if (harqEntities_.knows(peer)) 00474 { 00475 return harqEntities_.find(peer)->hasReceiverCapacity(); 00476 } 00477 return true; 00478 } 00479 00480 void 00481 HARQ::schedulePeerRetransmissions(wns::scheduler::UserID peer, int processID) 00482 { 00483 if(harqEntities_.knows(peer)) 00484 { 00485 return harqEntities_.find(peer)->schedulePeerRetransmissions(processID); 00486 } 00487 } 00488 00489 void 00490 HARQ::sendPendingFeedback() 00491 { 00492 for(HARQEntityContainer::const_iterator it = harqEntities_.begin(); 00493 it != harqEntities_.end(); 00494 ++it) 00495 { 00496 it->second->sendPendingFeedback(); 00497 } 00498 } 00499 00500 HARQEntity::HARQEntity(const wns::pyconfig::View& config, int numSenderProcesses, int numReceiverProcesses, int numRVs, int retransmissionLimit, wns::logger::Logger logger): 00501 numSenderProcesses_(numSenderProcesses), 00502 numReceiverProcesses_(numReceiverProcesses), 00503 numRVs_(numRVs), 00504 retransmissionLimit_(retransmissionLimit), 00505 logger_(logger), 00506 scheduledPeerRetransmissionCounter_(0) 00507 { 00508 decoder_ = std::auto_ptr<IDecoder>(STATIC_FACTORY_NEW_INSTANCE(IDecoder, wns::PyConfigViewCreator, config.get("decoder"), config.get("decoder"))); 00509 00510 for (int ii=0; ii < numSenderProcesses_; ++ii) 00511 { 00512 senderProcesses_.push_back(HARQSenderProcess(this, ii, numRVs_, config.get<int>("retransmissionLimit"), logger_)); 00513 } 00514 00515 for (int ii=0; ii < numReceiverProcesses_; ++ii) 00516 { 00517 receiverProcesses_.push_back(HARQReceiverProcess(config.get("receiverConfig"), this, ii, numRVs_, config.get<int>("retransmissionLimit"), logger_)); 00518 } 00522 } 00523 00524 HARQEntity::HARQEntity(const HARQEntity& other): 00525 senderProcesses_(other.senderProcesses_), 00526 receiverProcesses_(other.receiverProcesses_), 00527 numSenderProcesses_(other.numSenderProcesses_), 00528 numReceiverProcesses_(other.numReceiverProcesses_), 00529 numRVs_(other.numRVs_), 00530 retransmissionLimit_(other.retransmissionLimit_), 00531 logger_(other.logger_), 00532 scheduledPeerRetransmissionCounter_(other.scheduledPeerRetransmissionCounter_), 00533 decoder_(wns::clone(other.decoder_)) 00534 { 00535 for (int ii=0; ii < numSenderProcesses_; ++ii) 00536 { 00537 senderProcesses_[ii].setEntity(this); 00538 } 00539 00540 for (int ii=0; ii < numReceiverProcesses_; ++ii) 00541 { 00542 receiverProcesses_[ii].setEntity(this); 00543 } 00544 } 00545 00546 void 00547 HARQEntity::newTransmission(long int transportBlockID, const wns::scheduler::SchedulingTimeSlotPtr& resourceBlock) 00548 { 00549 //assure(resourceBlock->physicalResources[0].hasScheduledCompounds(), "No resources in RB"); 00550 00551 if (!resourceBlock->isHARQEnabled()) 00552 { 00553 return; 00554 } 00555 00556 assure(hasCapacity(transportBlockID), "HARQ Entity is busy but you wanted to start a new transmission!"); 00557 00558 // find free sender process 00559 for (int ii=0; ii < numSenderProcesses_; ++ii) 00560 { 00561 if (senderProcesses_[ii].hasCapacity(transportBlockID)) 00562 { 00563 // Let process put in proper HARQInfo 00564 senderProcesses_[ii].newTransmission(transportBlockID, resourceBlock); 00565 00566 MESSAGE_SINGLE(NORMAL, logger_, "newTransmission for sender process " << ii << "(TID: " << transportBlockID << ")"); 00567 return; // break; // found 00568 } 00569 } 00570 assure(false, "HARQEntity::newTransmission: cannot find free senderProcess"); 00571 } 00572 00573 bool 00574 HARQEntity::hasCapacity(long int transportBlockID) 00575 { 00576 for (int ii=0; ii < numSenderProcesses_; ++ii) 00577 { 00578 // Any of my send processes idle? 00579 if (senderProcesses_[ii].hasCapacity(transportBlockID)) 00580 { 00581 return true; 00582 } 00583 } 00584 return false; 00585 } 00586 00587 bool 00588 HARQEntity::hasReceiverCapacity() 00589 { 00590 int count = 0; 00591 for (int ii=0; ii < numReceiverProcesses_; ++ii) 00592 { 00593 // Any of my send processes idle? 00594 if (!receiverProcesses_[ii].isFree()) 00595 { 00596 count++; 00597 } 00598 } 00599 00600 if (count > 7) 00601 { 00602 return false; 00603 } 00604 00605 return true; 00606 } 00607 00608 void 00609 HARQEntity::onTimeSlotReceived(const wns::scheduler::SchedulingTimeSlotPtr& resourceBlock, 00610 HARQInterface::TimeSlotInfo info) 00611 { 00612 if (!resourceBlock->isHARQEnabled()) 00613 { 00614 return; 00615 } 00616 00617 assure(resourceBlock->harq.processID < receiverProcesses_.size(), "Invalid receiver processID=" << resourceBlock->harq.processID); 00618 receiverProcesses_[resourceBlock->harq.processID].onTimeSlotReceived(resourceBlock, info); 00619 00620 } 00621 00622 HARQInterface::DecodeStatusContainer 00623 HARQEntity::decode() 00624 { 00625 HARQInterface::DecodeStatusContainer tmp; 00626 00627 for (int ii=0; ii < numReceiverProcesses_; ++ii) 00628 { 00629 HARQInterface::DecodeStatusContainer perEntity; 00630 00631 perEntity = receiverProcesses_[ii].decode(); 00632 00633 HARQInterface::DecodeStatusContainer::iterator it; 00634 00635 for(it=perEntity.begin(); it!=perEntity.end(); ++it) 00636 { 00637 tmp.push_back(*it); 00638 } 00639 } 00640 return tmp; 00641 } 00642 00643 std::list<int> 00644 HARQEntity::getProcessesWithRetransmissions() const 00645 { 00646 std::list<int> tmp; 00647 00648 std::vector<HARQSenderProcess>::const_iterator it; 00649 00650 for(it = senderProcesses_.begin(); it != senderProcesses_.end(); ++it) 00651 { 00652 if (it->getNumberOfRetransmissions() > 0) 00653 { 00654 tmp.push_back(it->processID()); 00655 } 00656 } 00657 return tmp; 00658 } 00659 00660 int 00661 HARQEntity::getNumberOfRetransmissions(int processID) 00662 { 00663 return senderProcesses_[processID].getNumberOfRetransmissions(); 00664 } 00665 00666 bool 00667 HARQEntity::hasRetransmissions() 00668 { 00669 for (int ii=0; ii < numSenderProcesses_; ++ii) 00670 { 00671 if (senderProcesses_[ii].getNumberOfRetransmissions() > 0) 00672 { 00673 return true; 00674 } 00675 } 00676 return false; 00677 } 00678 00679 wns::scheduler::SchedulingTimeSlotPtr 00680 HARQEntity::getNextRetransmission(int processID) 00681 { 00682 return senderProcesses_[processID].getNextRetransmission(); 00683 } 00684 00685 wns::scheduler::SchedulingTimeSlotPtr 00686 HARQEntity::peekNextRetransmission(int processID) const 00687 { 00688 return senderProcesses_[processID].peekNextRetransmission(); 00689 } 00690 00691 std::list<int> 00692 HARQEntity::getPeerProcessesWithRetransmissions() const 00693 { 00694 std::list<int> tmp; 00695 00696 std::vector<HARQReceiverProcess>::const_iterator it; 00697 00698 for(it = receiverProcesses_.begin(); it != receiverProcesses_.end(); ++it) 00699 { 00700 if (it->numPendingPeerRetransmissions() > 0) 00701 { 00702 tmp.push_back(it->processID()); 00703 } 00704 } 00705 return tmp; 00706 } 00707 00708 int 00709 HARQEntity::getNumberOfPeerRetransmissions(int processID) const 00710 { 00711 return receiverProcesses_[processID].numPendingPeerRetransmissions(); 00712 } 00713 00714 void 00715 HARQEntity::schedulePeerRetransmissions(int processID) 00716 { 00717 receiverProcesses_[processID].schedulePeerRetransmissions(); 00718 } 00719 00720 void 00721 HARQEntity::sendPendingFeedback() 00722 { 00723 std::vector<HARQReceiverProcess>::iterator it; 00724 00725 for(it = receiverProcesses_.begin(); it != receiverProcesses_.end(); ++it) 00726 { 00727 it->sendPendingFeedback(); 00728 } 00729 } 00730 00731 HARQReceiverProcess::HARQReceiverProcess(const wns::pyconfig::View& config, HARQEntity* entity, int processID, int numRVs, int retransmissionLimit, wns::logger::Logger logger): 00732 entity_(entity), 00733 processID_(processID), 00734 numRVs_(numRVs), 00735 retransmissionLimit_(retransmissionLimit), 00736 logger_(logger), 00737 receptionBuffer_(numRVs), 00738 numPendingPeerRetransmissions_(0) 00739 { 00740 } 00741 00742 HARQReceiverProcess::HARQReceiverProcess(const HARQReceiverProcess& other): 00743 entity_(NULL), 00744 processID_(other.processID_), 00745 numRVs_(other.numRVs_), 00746 retransmissionLimit_(other.retransmissionLimit_), 00747 logger_(other.logger_), 00748 receptionBuffer_(other.numRVs_), 00749 numPendingPeerRetransmissions_(0), 00750 waitingForRetransmissions_(false) 00751 { 00752 } 00753 00754 void 00755 HARQReceiverProcess::setEntity(HARQEntity* entity) 00756 { 00757 entity_ = entity; 00758 } 00759 00760 void 00761 HARQReceiverProcess::endReception() 00762 { 00763 MESSAGE_SINGLE(NORMAL, logger_, "End Reception is now"); 00764 receptionDelta_ = wns::events::scheduler::IEventPtr(); 00765 } 00766 00767 void 00768 HARQReceiverProcess::onTimeSlotReceived(const wns::scheduler::SchedulingTimeSlotPtr& resourceBlock, HARQInterface::TimeSlotInfo info) 00769 { 00770 MESSAGE_BEGIN(NORMAL, logger_, m, "HarqReceiverProcess::receive processID = " << processID_); 00771 m << ", RV = " << resourceBlock->harq.rv << ", RetryCounter=" << resourceBlock->harq.retryCounter << ", SINR=" << info.powerMeasurement_->getSINR(); 00772 MESSAGE_END(); 00773 00774 // We received something, a new decoding attempt makes sense. 00775 waitingForRetransmissions_ = false; 00776 00777 if (receptionDelta_ == wns::events::scheduler::IEventPtr()) 00778 { 00779 if (resourceBlock->harq.NDI) 00780 { 00781 receptionBuffer_.clear(); 00782 } 00783 00784 // All timeslots of one frame arrive at the same time 00785 receptionDelta_= wns::simulator::getEventScheduler()->scheduleDelay(boost::bind(&HARQReceiverProcess::endReception, this), 0.000001); 00786 } 00787 00788 std::list<int> positions = receptionBuffer_.getAvailablePosInTB(); 00789 00790 if (positions.size() > 0) 00791 { 00792 // Not the first one 00793 int tid = receptionBuffer_.getEntriesForRV(positions.front(), 0).front().timeSlot_->harq.transportBlockID; 00794 assure(tid == resourceBlock->harq.transportBlockID, "More than on TID in a reception buffer is wrong.wrong.wrong."); 00795 } 00796 00797 SchedulingTimeSlotInfo tsinfo(resourceBlock, info.powerMeasurement_); 00798 00799 if (resourceBlock->harq.ackCallback.empty()) 00800 { 00801 std::cout << "Tried to store resource block with empty ack callback" << std::endl; 00802 exit(1); 00803 } 00804 00805 if (resourceBlock->harq.nackCallback.empty()) 00806 { 00807 std::cout << "Tried to store resource block with empty nack callback" << std::endl; 00808 exit(1); 00809 } 00810 00811 receptionBuffer_.appendEntryForRV(resourceBlock->harq.tbPos, resourceBlock->harq.rv, tsinfo); 00812 00813 return; 00814 } 00815 00816 HARQInterface::DecodeStatusContainer 00817 HARQReceiverProcess::decode() 00818 { 00819 HARQInterface::DecodeStatusContainer tmp; 00820 00821 if (waitingForRetransmissions_) 00822 { 00823 // No changes since last decode. Do nothing. 00824 return tmp; 00825 } 00826 00827 std::list<int> positions = receptionBuffer_.getAvailablePosInTB(); 00828 00829 // Nothing received, nothing to decode 00830 if(positions.size() == 0) 00831 { 00832 return tmp; 00833 } 00834 00835 // After we leave this function we will always be waiting for new input 00836 waitingForRetransmissions_ = true; 00837 00838 int transportBlockID = receptionBuffer_.getEntriesForRV(positions.front(), 0).front().timeSlot_->harq.transportBlockID; 00839 if(entity_->decoder_->canDecode(receptionBuffer_)) 00840 { 00841 MESSAGE_SINGLE(NORMAL, logger_, "HARQReceiver processID=" << processID_ << " sucessful decoded" 00842 << " on transportBlock "<< transportBlockID); 00843 // Next frame is not necessarily the right direction 00844 // If e.g. in TDD Uplink we need to wait with the feedback 00845 // until the next UL frame. 00846 // sendPendingFeedback will then be triggered by the Timingscheduler 00847 HARQReceiverProcess::Feedback fb; 00848 fb.callback_ = receptionBuffer_.getEntriesForRV(positions.front(), 0).front().timeSlot_->harq.ackCallback; 00849 fb.retransmissionLimitHit_ = false; 00850 00851 pendingFeedback_.push_back(fb); 00852 00853 std::list<int>::iterator it; 00854 00855 for(it=positions.begin();it!=positions.end();++it) 00856 { 00857 wns::scheduler::SchedulingTimeSlotPtr ts; 00858 ts = receptionBuffer_.getEntriesForRV(*it, 0).front().timeSlot_; 00859 ts->harq.successfullyDecoded = true; 00860 tmp.push_back(HARQInterface::DecodeStatusContainerEntry(ts, 00861 HARQInterface::TimeSlotInfo(wns::service::phy::power::PowerMeasurementPtr(), 0) 00862 )); 00863 } 00864 00865 receptionBuffer_.clear(); 00866 numPendingPeerRetransmissions_ = 0; 00867 } 00868 else 00869 { 00870 int retryCounter= receptionBuffer_.getEntriesForRV(positions.front(), 0).back().timeSlot_->harq.retryCounter; 00871 00872 MESSAGE_SINGLE(NORMAL, logger_, "HARQReceiver processID=" << processID_ << " failed to decode" 00873 << " on transportBlock "<< transportBlockID << " Retries: " << retryCounter); 00874 00875 HARQReceiverProcess::Feedback fb; 00876 fb.callback_ = receptionBuffer_.getEntriesForRV(positions.front(), 0).front().timeSlot_->harq.nackCallback; 00877 fb.retransmissionLimitHit_ = retryCounter >= retransmissionLimit_; 00878 00879 // Same is true for the NACKs 00880 pendingFeedback_.push_back(fb); 00881 00882 if(retryCounter >= retransmissionLimit_) 00883 { 00884 MESSAGE_SINGLE(NORMAL, logger_, "HARQReceiver processID=" << processID_ << " retransmission limit of " 00885 << retransmissionLimit_ << " exceeded! Dropping resource blocks"); 00886 00887 receptionBuffer_.clear(); 00888 setNumPendingPeerRetransmissions(0); 00889 } 00890 } 00891 return tmp; 00892 } 00893 00894 void 00895 HARQReceiverProcess::setNumPendingPeerRetransmissions(int num) 00896 { 00897 MESSAGE_SINGLE(NORMAL, logger_, "setNumPendingPeerRetransmissins(" << num << ")"); 00898 numPendingPeerRetransmissions_ = num; 00899 } 00900 00901 void 00902 HARQReceiverProcess::sendPendingFeedback() 00903 { 00904 BOOST_FOREACH(HARQReceiverProcess::Feedback fb, pendingFeedback_) 00905 { 00906 if(!fb.callback_.empty()) 00907 { 00908 fb.callback_(); 00909 } 00910 else 00911 { 00912 std::cout << "Empty callback in HARQReceiverProcess::sendPendingFeedback()" << std::endl; 00913 exit(1); 00914 } 00915 } 00916 00917 if (pendingFeedback_.size() > 0) 00918 { 00919 if (!pendingFeedback_.front().retransmissionLimitHit_) 00920 { 00921 // Receiver of feedback needs processing delay, only then 00922 // the retransmissions are available, and only then report 00923 // peer retransmissions to our local uplink scheduler 00924 std::list<int> positions = receptionBuffer_.getAvailablePosInTB(); 00925 00926 wns::simulator::getEventScheduler()->scheduleDelay(boost::bind(&HARQReceiverProcess::setNumPendingPeerRetransmissions, this, positions.size()), 0.001999); 00927 } 00928 pendingFeedback_.clear(); 00929 } 00930 00931 } 00932 00933 void 00934 HARQReceiverProcess::schedulePeerRetransmissions() 00935 { 00936 setNumPendingPeerRetransmissions(0); 00937 } 00938 00939 int 00940 HARQReceiverProcess::numPendingPeerRetransmissions() const 00941 { 00942 return numPendingPeerRetransmissions_; 00943 } 00944 00945 int 00946 HARQReceiverProcess::processID() const 00947 { 00948 return processID_; 00949 } 00950 00951 SoftCombiningContainer 00952 HARQReceiverProcess::receptionBuffer() const 00953 { 00954 return receptionBuffer_; 00955 } 00956 00957 wns::scheduler::SchedulingTimeSlotPtr 00958 HARQReceiverProcess::schedulingTimeSlot() const 00959 { 00960 assure(false, "Need to fix this,i.e. the decoding"); 00961 return wns::scheduler::SchedulingTimeSlotPtr(); 00962 } 00963 00964 bool 00965 HARQReceiverProcess::isFree() const 00966 { 00967 return (receptionBuffer_.getAvailablePosInTB().size() == 0); 00968 } 00969 00970 HARQSenderProcess::HARQSenderProcess(HARQEntity* entity, int processID, int numRVs, int retransmissionLimit, wns::logger::Logger logger): 00971 entity_(entity), 00972 processID_(processID), 00973 numRVs_(numRVs), 00974 retransmissionLimit_(retransmissionLimit), 00975 logger_(logger), 00976 transportBlockID_(0), 00977 retransmissionCounter_(0), 00978 NDI_(true), 00979 nextPositionInTB_(0), 00980 pendingRetransmissions_() 00981 { 00982 } 00983 00984 void 00985 HARQSenderProcess::setEntity(HARQEntity* entity) 00986 { 00987 entity_ = entity; 00988 } 00989 00990 void 00991 HARQSenderProcess::newTransmission(long int transportBlockID, 00992 const wns::scheduler::SchedulingTimeSlotPtr& resourceBlock) 00993 { 00994 assure(resourceBlock->physicalResources[0].hasScheduledCompounds(), "No resources in RB"); 00995 assure(hasCapacity(transportBlockID), "HARQSender Process " << processID_ << " is busy but you wanted to start a new transmission!"); 00996 00997 BOOST_FOREACH(wns::scheduler::SchedulingTimeSlotPtr& slot, timeslots_) 00998 { 00999 int sc = resourceBlock->physicalResources[0].getSubChannelIndex(); 01000 int oldsc = slot->physicalResources[0].getSubChannelIndex(); 01001 assure(oldsc != sc, "Duplicate transmission for SC " << sc << " detected"); 01002 } 01003 01004 transportBlockID_ = transportBlockID; 01005 01006 resourceBlock->harq.processID = processID_; 01007 resourceBlock->harq.rv = 0; 01008 resourceBlock->harq.ackCallback = boost::bind(&HARQSenderProcess::ACK, this); 01009 resourceBlock->harq.nackCallback = boost::bind(&HARQSenderProcess::NACK, this); 01010 resourceBlock->harq.NDI = true; 01011 resourceBlock->harq.transportBlockID = transportBlockID_; 01012 resourceBlock->harq.tbPos = nextPositionInTB_; 01013 01014 nextPositionInTB_++; 01015 01016 // Take a copy 01017 wns::scheduler::SchedulingTimeSlot* theCopy = NULL; 01018 // Only after that we store a copy 01019 theCopy = new wns::scheduler::SchedulingTimeSlot(*resourceBlock); 01020 01021 theCopy->consistencyCheck(); 01022 01023 timeslots_.push_back(wns::scheduler::SchedulingTimeSlotPtr(theCopy)); 01024 01025 assure(theCopy->physicalResources[0].hasScheduledCompounds(), "No resources in RB"); 01026 } 01027 01028 bool 01029 HARQSenderProcess::hasCapacity(long int transportBlockID) 01030 { 01031 bool hasCapacity = (transportBlockID_ == 0 || transportBlockID_ == transportBlockID); 01032 01033 if (hasCapacity) 01034 { 01035 MESSAGE_BEGIN(VERBOSE, logger_, m, "HARQSender processID=" << processID_); 01036 m << ", TID=" << transportBlockID_; 01037 m << ", TIDreq=" << transportBlockID; 01038 m << " has capacity"; 01039 MESSAGE_END(); 01040 } 01041 else 01042 { 01043 MESSAGE_BEGIN(VERBOSE, logger_, m, "HARQSender processID=" << processID_); 01044 m << ", TID=" << transportBlockID_; 01045 m << ", TIDreq=" << transportBlockID; 01046 m << " has no capacity"; 01047 MESSAGE_END(); 01048 } 01049 return hasCapacity; 01050 } 01051 01052 void 01053 HARQSenderProcess::ACK() 01054 { 01055 // after approx 3ms processing delay 01056 wns::simulator::getEventScheduler()->scheduleDelay( 01057 boost::bind(&HARQSenderProcess::postDecodingACK, this), 0.002999); 01058 } 01059 01060 void 01061 HARQSenderProcess::postDecodingACK() 01062 { 01063 MESSAGE_SINGLE(NORMAL, logger_, "HARQSender processID=" << processID_ << " received ACK" 01064 << " on transportBlock "<< transportBlockID_); 01065 transportBlockID_ = 0; 01066 nextPositionInTB_ = 0; 01067 NDI_ = true; 01068 retransmissionCounter_ = 0; 01069 timeslots_.clear(); 01070 } 01071 01072 void 01073 HARQSenderProcess::NACK() 01074 { 01075 // after approx 3ms processing delay 01076 wns::simulator::getEventScheduler()->scheduleDelay( 01077 boost::bind(&HARQSenderProcess::postDecodingNACK, this), 0.002999); 01078 } 01079 01080 void 01081 HARQSenderProcess::postDecodingNACK() 01082 { 01083 if(transportBlockID_ == 0) 01084 { 01085 MESSAGE_SINGLE(NORMAL, logger_, "WARNING: RECEIVED NACK but resourceBlock_ is empty"); 01086 return; 01087 } 01088 01089 //MESSAGE_SINGLE(NORMAL, logger_, "HARQ process " << processID_ << " received NACK"); 01090 MESSAGE_SINGLE(NORMAL, logger_, "HARQSender processID=" << processID_ << " received NACK" 01091 <<" on transportBlock "<< transportBlockID_); 01092 01093 NDI_ = false; 01094 retransmissionCounter_++; 01095 01096 // at most 3 retransmissions 01097 if (retransmissionCounter_ > retransmissionLimit_) { 01098 MESSAGE_SINGLE(NORMAL, logger_, "HARQSender processID=" << processID_ << " retransmission limit of " 01099 << retransmissionLimit_ << " exceeded! Dropping resource blocks"); 01100 transportBlockID_ = 0; 01101 retransmissionCounter_ = 0; 01102 nextPositionInTB_ = 0; 01103 timeslots_.clear(); 01104 } 01105 else 01106 { 01107 // Take a copy and enqueue retransmission 01108 TimeSlotList::iterator it; 01109 for (it=timeslots_.begin(); it!=timeslots_.end(); ++it) 01110 { 01111 wns::scheduler::SchedulingTimeSlot* theCopy = NULL; 01112 wns::scheduler::SchedulingTimeSlotPtr resourceBlock = *it; 01113 theCopy = new wns::scheduler::SchedulingTimeSlot(*resourceBlock); 01114 wns::scheduler::SchedulingTimeSlotPtr retransmission = wns::scheduler::SchedulingTimeSlotPtr(theCopy); 01115 retransmission->consistencyCheck(); 01116 retransmission->harq.NDI = NDI_; 01117 retransmission->harq.processID = processID_; 01118 retransmission->harq.transportBlockID = transportBlockID_; 01119 retransmission->harq.retryCounter = retransmissionCounter_; 01120 01121 if (retransmission->harq.ackCallback.empty()) 01122 { 01123 std::cout << "Trying to retransmit resource block with empty ack callback in HARQSenderProcess::posDecodingNACK" << std::endl; 01124 exit(1); 01125 } 01126 01127 if (retransmission->harq.nackCallback.empty()) 01128 { 01129 std::cout << "Trying to retransmit resource block with empty nack callback in HARQSenderProcess::posDecodingNACK" << std::endl; 01130 exit(1); 01131 } 01132 01133 pendingRetransmissions_.push_back(retransmission); 01134 } 01135 } 01136 } 01137 01138 int 01139 HARQSenderProcess::getNumberOfRetransmissions() const 01140 { 01141 return pendingRetransmissions_.size(); 01142 } 01143 01144 wns::scheduler::SchedulingTimeSlotPtr 01145 HARQSenderProcess::getNextRetransmission() 01146 { 01147 wns::scheduler::SchedulingTimeSlotPtr r; 01148 01149 if (pendingRetransmissions_.size() > 0) 01150 { 01151 r = pendingRetransmissions_.front(); 01152 pendingRetransmissions_.pop_front(); 01153 } 01154 01155 if (r != wns::scheduler::SchedulingTimeSlotPtr()) 01156 { 01157 if (r->harq.ackCallback.empty()) 01158 { 01159 std::cout << "Returning empty ack callback in HARQSenderProcess::getNextRetransmission" << std::endl; 01160 exit(1); 01161 } 01162 01163 if (r->harq.nackCallback.empty()) 01164 { 01165 std::cout << "Returning empty nack callback in HARQSenderProcess::getNextRetransmission" << std::endl; 01166 exit(1); 01167 } 01168 } 01169 01170 return r; 01171 } 01172 01173 wns::scheduler::SchedulingTimeSlotPtr 01174 HARQSenderProcess::peekNextRetransmission() const 01175 { 01176 wns::scheduler::SchedulingTimeSlotPtr r; 01177 01178 if (pendingRetransmissions_.size() > 0) 01179 { 01180 r = pendingRetransmissions_.front(); 01181 } 01182 01183 return r; 01184 01185 } 01186 01187 int 01188 HARQSenderProcess::processID() const 01189 { 01190 return processID_; 01191 }
1.5.5