User Manual, Developers Guide and API Documentation

HARQ.cpp

Go to the documentation of this file.
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 }

Generated on Sun May 27 03:31:44 2012 for openWNS by  doxygen 1.5.5