Get rid of requestCauses. Use timestamped queue to make
sure we don't re-request bus prematurely. Use callback to avoid calling sendRetry() recursively within recvTiming. --HG-- extra : convert_revision : a907a2781b4b00aa8eb1ea7147afc81d6b424140
This commit is contained in:
parent
47bce8ef78
commit
529f12a531
9 changed files with 137 additions and 97 deletions
6
src/mem/cache/base_cache.cc
vendored
6
src/mem/cache/base_cache.cc
vendored
|
@ -42,7 +42,7 @@ using namespace std;
|
|||
|
||||
BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache)
|
||||
: SimpleTimingPort(_name, _cache), cache(_cache), otherPort(NULL),
|
||||
blocked(false), mustSendRetry(false), requestCauses(0)
|
||||
blocked(false), mustSendRetry(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,9 @@ BaseCache::CachePort::clearBlocked()
|
|||
{
|
||||
DPRINTF(Cache, "Cache Sending Retry\n");
|
||||
mustSendRetry = false;
|
||||
sendRetry();
|
||||
SendRetryEvent *ev = new SendRetryEvent(this, true);
|
||||
// @TODO: need to find a better time (next bus cycle?)
|
||||
ev->schedule(curTick + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
42
src/mem/cache/base_cache.hh
vendored
42
src/mem/cache/base_cache.hh
vendored
|
@ -41,6 +41,7 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "base/misc.hh"
|
||||
|
@ -105,6 +106,9 @@ class BaseCache : public MemObject
|
|||
|
||||
bool recvRetryCommon();
|
||||
|
||||
typedef EventWrapper<Port, &Port::sendRetry>
|
||||
SendRetryEvent;
|
||||
|
||||
public:
|
||||
void setOtherPort(CachePort *_otherPort) { otherPort = _otherPort; }
|
||||
|
||||
|
@ -120,27 +124,12 @@ class BaseCache : public MemObject
|
|||
|
||||
bool mustSendRetry;
|
||||
|
||||
/**
|
||||
* Bit vector for the outstanding requests for the master interface.
|
||||
*/
|
||||
uint8_t requestCauses;
|
||||
|
||||
bool isBusRequested() { return requestCauses != 0; }
|
||||
|
||||
void requestBus(RequestCause cause, Tick time)
|
||||
{
|
||||
DPRINTF(Cache, "Asserting bus request for cause %d\n", cause);
|
||||
if (!isBusRequested() && !waitingOnRetry) {
|
||||
assert(!sendEvent->scheduled());
|
||||
sendEvent->schedule(time);
|
||||
if (!waitingOnRetry) {
|
||||
schedSendEvent(time);
|
||||
}
|
||||
requestCauses |= (1 << cause);
|
||||
}
|
||||
|
||||
void deassertBusRequest(RequestCause cause)
|
||||
{
|
||||
DPRINTF(Cache, "Deasserting bus request for cause %d\n", cause);
|
||||
requestCauses &= ~(1 << cause);
|
||||
}
|
||||
|
||||
void respond(PacketPtr pkt, Tick time) {
|
||||
|
@ -163,8 +152,7 @@ class BaseCache : public MemObject
|
|||
MSHR *allocateBufferInternal(MSHRQueue *mq, Addr addr, int size,
|
||||
PacketPtr pkt, Tick time, bool requestBus)
|
||||
{
|
||||
MSHR *mshr = mq->allocate(addr, size, pkt);
|
||||
mshr->order = order++;
|
||||
MSHR *mshr = mq->allocate(addr, size, pkt, time, order++);
|
||||
|
||||
if (mq->isFull()) {
|
||||
setBlocked((BlockedCause)mq->index);
|
||||
|
@ -182,9 +170,6 @@ class BaseCache : public MemObject
|
|||
MSHRQueue *mq = mshr->queue;
|
||||
bool wasFull = mq->isFull();
|
||||
mq->markInService(mshr);
|
||||
if (!mq->havePending()) {
|
||||
deassertMemSideBusRequest((RequestCause)mq->index);
|
||||
}
|
||||
if (wasFull && !mq->isFull()) {
|
||||
clearBlocked((BlockedCause)mq->index);
|
||||
}
|
||||
|
@ -491,13 +476,10 @@ class BaseCache : public MemObject
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the memory-side bus should be requested.
|
||||
* @return True if there are outstanding requests for the master bus.
|
||||
*/
|
||||
bool isMemSideBusRequested()
|
||||
Tick nextMSHRReadyTick()
|
||||
{
|
||||
return memSidePort->isBusRequested();
|
||||
return std::min(mshrQueue.nextMSHRReadyTick(),
|
||||
writeBuffer.nextMSHRReadyTick());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -516,7 +498,9 @@ class BaseCache : public MemObject
|
|||
*/
|
||||
void deassertMemSideBusRequest(RequestCause cause)
|
||||
{
|
||||
memSidePort->deassertBusRequest(cause);
|
||||
// obsolete!!
|
||||
assert(false);
|
||||
// memSidePort->deassertBusRequest(cause);
|
||||
// checkDrain();
|
||||
}
|
||||
|
||||
|
|
28
src/mem/cache/cache_impl.hh
vendored
28
src/mem/cache/cache_impl.hh
vendored
|
@ -185,9 +185,6 @@ Cache<TagStore,Coherence>::squash(int threadNum)
|
|||
cause = Blocked_NoMSHRs;
|
||||
}
|
||||
mshrQueue.squash(threadNum);
|
||||
if (!mshrQueue.havePending()) {
|
||||
deassertMemSideBusRequest(Request_MSHR);
|
||||
}
|
||||
if (unblock && !mshrQueue.isFull()) {
|
||||
clearBlocked(cause);
|
||||
}
|
||||
|
@ -368,11 +365,14 @@ Cache<TagStore,Coherence>::timingAccess(PacketPtr pkt)
|
|||
if (mshr->threadNum != 0/*pkt->req->getThreadNum()*/) {
|
||||
mshr->threadNum = -1;
|
||||
}
|
||||
mshr->allocateTarget(pkt);
|
||||
mshr->allocateTarget(pkt, time, order++);
|
||||
if (mshr->getNumTargets() == numTarget) {
|
||||
noTargetMSHR = mshr;
|
||||
setBlocked(Blocked_NoTargets);
|
||||
mshrQueue.moveToFront(mshr);
|
||||
// need to be careful with this... if this mshr isn't
|
||||
// ready yet (i.e. time > curTick_, we don't want to
|
||||
// move it ahead of mshrs that are ready
|
||||
// mshrQueue.moveToFront(mshr);
|
||||
}
|
||||
} else {
|
||||
// no MSHR
|
||||
|
@ -630,7 +630,6 @@ Cache<TagStore,Coherence>::satisfyMSHR(MSHR *mshr, PacketPtr pkt,
|
|||
if (mshr->promoteDeferredTargets()) {
|
||||
MSHRQueue *mq = mshr->queue;
|
||||
mq->markPending(mshr);
|
||||
mshr->order = order++;
|
||||
requestMemSideBus((RequestCause)mq->index, pkt->finishTime);
|
||||
return false;
|
||||
}
|
||||
|
@ -879,7 +878,7 @@ Cache<TagStore,Coherence>::snoopTiming(PacketPtr pkt)
|
|||
// we have outstanding...
|
||||
if (mshr && mshr->inService) {
|
||||
assert(mshr->getNumTargets() < numTarget); //handle later
|
||||
mshr->allocateSnoopTarget(pkt);
|
||||
mshr->allocateSnoopTarget(pkt, curTick, order++);
|
||||
assert(mshr->getNumTargets() < numTarget); //handle later
|
||||
return;
|
||||
}
|
||||
|
@ -1202,6 +1201,7 @@ Cache<TagStore,Coherence>::MemSidePort::sendPacket()
|
|||
} else {
|
||||
// check for non-response packets (requests & writebacks)
|
||||
PacketPtr pkt = myCache()->getTimingPacket();
|
||||
assert(pkt != NULL);
|
||||
MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
|
||||
|
||||
bool success = sendTiming(pkt);
|
||||
|
@ -1220,14 +1220,12 @@ Cache<TagStore,Coherence>::MemSidePort::sendPacket()
|
|||
// tried to send packet... if it was successful (no retry), see if
|
||||
// we need to rerequest bus or not
|
||||
if (!waitingOnRetry) {
|
||||
if (isBusRequested()) {
|
||||
// more requests/writebacks: rerequest ASAP
|
||||
DPRINTF(CachePort, "still more MSHR requests to send\n");
|
||||
sendEvent->schedule(curTick+1);
|
||||
} else if (!transmitList.empty()) {
|
||||
// deferred packets: rerequest bus, but possibly not until later
|
||||
Tick time = transmitList.front().tick;
|
||||
sendEvent->schedule(time <= curTick ? curTick+1 : time);
|
||||
Tick nextReady = std::min(deferredPacketReadyTick(),
|
||||
myCache()->nextMSHRReadyTick());
|
||||
// @TODO: need to facotr in prefetch requests here somehow
|
||||
if (nextReady != MaxTick) {
|
||||
DPRINTF(CachePort, "more packets to send @ %d\n", nextReady);
|
||||
sendEvent->schedule(std::max(nextReady, curTick + 1));
|
||||
} else {
|
||||
// no more to send right now: if we're draining, we may be done
|
||||
if (drainEvent) {
|
||||
|
|
24
src/mem/cache/miss/mshr.cc
vendored
24
src/mem/cache/miss/mshr.cc
vendored
|
@ -37,6 +37,7 @@
|
|||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "mem/cache/miss/mshr.hh"
|
||||
#include "sim/core.hh" // for curTick
|
||||
|
@ -54,10 +55,13 @@ MSHR::MSHR()
|
|||
}
|
||||
|
||||
void
|
||||
MSHR::allocate(Addr _addr, int _size, PacketPtr target)
|
||||
MSHR::allocate(Addr _addr, int _size, PacketPtr target,
|
||||
Tick when, Counter _order)
|
||||
{
|
||||
addr = _addr;
|
||||
size = _size;
|
||||
readyTick = when;
|
||||
order = _order;
|
||||
assert(target);
|
||||
isCacheFill = false;
|
||||
needsExclusive = target->needsExclusive();
|
||||
|
@ -66,8 +70,8 @@ MSHR::allocate(Addr _addr, int _size, PacketPtr target)
|
|||
threadNum = 0;
|
||||
ntargets = 1;
|
||||
// Don't know of a case where we would allocate a new MSHR for a
|
||||
// snoop (mem0-side request), so set cpuSide to true here.
|
||||
targets.push_back(Target(target, true));
|
||||
// snoop (mem-side request), so set cpuSide to true here.
|
||||
targets.push_back(Target(target, when, _order, true));
|
||||
assert(deferredTargets.empty());
|
||||
deferredNeedsExclusive = false;
|
||||
pendingInvalidate = false;
|
||||
|
@ -88,33 +92,33 @@ MSHR::deallocate()
|
|||
* Adds a target to an MSHR
|
||||
*/
|
||||
void
|
||||
MSHR::allocateTarget(PacketPtr target)
|
||||
MSHR::allocateTarget(PacketPtr target, Tick when, Counter _order)
|
||||
{
|
||||
if (inService) {
|
||||
if (!deferredTargets.empty() || pendingInvalidate ||
|
||||
(!needsExclusive && target->needsExclusive())) {
|
||||
// need to put on deferred list
|
||||
deferredTargets.push_back(Target(target, true));
|
||||
deferredTargets.push_back(Target(target, when, _order, true));
|
||||
if (target->needsExclusive()) {
|
||||
deferredNeedsExclusive = true;
|
||||
}
|
||||
} else {
|
||||
// still OK to append to outstanding request
|
||||
targets.push_back(Target(target, true));
|
||||
targets.push_back(Target(target, when, _order, true));
|
||||
}
|
||||
} else {
|
||||
if (target->needsExclusive()) {
|
||||
needsExclusive = true;
|
||||
}
|
||||
|
||||
targets.push_back(Target(target, true));
|
||||
targets.push_back(Target(target, when, _order, true));
|
||||
}
|
||||
|
||||
++ntargets;
|
||||
}
|
||||
|
||||
void
|
||||
MSHR::allocateSnoopTarget(PacketPtr target)
|
||||
MSHR::allocateSnoopTarget(PacketPtr target, Tick when, Counter _order)
|
||||
{
|
||||
assert(inService); // don't bother to call otherwise
|
||||
|
||||
|
@ -137,7 +141,7 @@ MSHR::allocateSnoopTarget(PacketPtr target)
|
|||
return;
|
||||
}
|
||||
|
||||
targets.push_back(Target(target, false));
|
||||
targets.push_back(Target(target, when, _order, false));
|
||||
++ntargets;
|
||||
}
|
||||
|
||||
|
@ -157,6 +161,8 @@ MSHR::promoteDeferredTargets()
|
|||
needsExclusive = deferredNeedsExclusive;
|
||||
pendingInvalidate = false;
|
||||
deferredNeedsExclusive = false;
|
||||
order = targets.front().order;
|
||||
readyTick = std::max(curTick, targets.front().time);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
26
src/mem/cache/miss/mshr.hh
vendored
26
src/mem/cache/miss/mshr.hh
vendored
|
@ -55,13 +55,14 @@ class MSHR : public Packet::SenderState
|
|||
class Target {
|
||||
public:
|
||||
Tick time; //!< Time when request was received (for stats)
|
||||
Counter order; //!< Global order (for memory consistency mgmt)
|
||||
PacketPtr pkt; //!< Pending request packet.
|
||||
bool cpuSide; //!< Did request come from cpu side or mem side?
|
||||
|
||||
bool isCpuSide() { return cpuSide; }
|
||||
|
||||
Target(PacketPtr _pkt, bool _cpuSide, Tick _time = curTick)
|
||||
: time(_time), pkt(_pkt), cpuSide(_cpuSide)
|
||||
Target(PacketPtr _pkt, Tick _time, Counter _order, bool _cpuSide)
|
||||
: time(_time), order(_order), pkt(_pkt), cpuSide(_cpuSide)
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -79,6 +80,12 @@ class MSHR : public Packet::SenderState
|
|||
/** Pointer to queue containing this MSHR. */
|
||||
MSHRQueue *queue;
|
||||
|
||||
/** Cycle when ready to issue */
|
||||
Tick readyTick;
|
||||
|
||||
/** Order number assigned by the miss queue. */
|
||||
Counter order;
|
||||
|
||||
/** Address of the request. */
|
||||
Addr addr;
|
||||
|
||||
|
@ -103,8 +110,6 @@ class MSHR : public Packet::SenderState
|
|||
short threadNum;
|
||||
/** The number of currently allocated targets. */
|
||||
short ntargets;
|
||||
/** Order number of assigned by the miss queue. */
|
||||
uint64_t order;
|
||||
|
||||
/**
|
||||
* Pointer to this MSHR on the ready list.
|
||||
|
@ -136,13 +141,8 @@ public:
|
|||
* @param size The number of bytes to request.
|
||||
* @param pkt The original miss.
|
||||
*/
|
||||
void allocate(Addr addr, int size, PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* Allocate this MSHR as a buffer for the given request.
|
||||
* @param target The memory request to buffer.
|
||||
*/
|
||||
void allocateAsBuffer(PacketPtr target);
|
||||
void allocate(Addr addr, int size, PacketPtr pkt,
|
||||
Tick when, Counter _order);
|
||||
|
||||
/**
|
||||
* Mark this MSHR as free.
|
||||
|
@ -153,8 +153,8 @@ public:
|
|||
* Add a request to the list of targets.
|
||||
* @param target The target.
|
||||
*/
|
||||
void allocateTarget(PacketPtr target);
|
||||
void allocateSnoopTarget(PacketPtr target);
|
||||
void allocateTarget(PacketPtr target, Tick when, Counter order);
|
||||
void allocateSnoopTarget(PacketPtr target, Tick when, Counter order);
|
||||
|
||||
/** A simple constructor. */
|
||||
MSHR();
|
||||
|
|
45
src/mem/cache/miss/mshr_queue.cc
vendored
45
src/mem/cache/miss/mshr_queue.cc
vendored
|
@ -90,8 +90,8 @@ MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const
|
|||
MSHR *
|
||||
MSHRQueue::findPending(Addr addr, int size) const
|
||||
{
|
||||
MSHR::ConstIterator i = pendingList.begin();
|
||||
MSHR::ConstIterator end = pendingList.end();
|
||||
MSHR::ConstIterator i = readyList.begin();
|
||||
MSHR::ConstIterator end = readyList.end();
|
||||
for (; i != end; ++i) {
|
||||
MSHR *mshr = *i;
|
||||
if (mshr->addr < addr) {
|
||||
|
@ -107,17 +107,37 @@ MSHRQueue::findPending(Addr addr, int size) const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
MSHR::Iterator
|
||||
MSHRQueue::addToReadyList(MSHR *mshr)
|
||||
{
|
||||
if (readyList.empty() || readyList.back()->readyTick <= mshr->readyTick) {
|
||||
return readyList.insert(readyList.end(), mshr);
|
||||
}
|
||||
|
||||
MSHR::Iterator i = readyList.begin();
|
||||
MSHR::Iterator end = readyList.end();
|
||||
for (; i != end; ++i) {
|
||||
if ((*i)->readyTick > mshr->readyTick) {
|
||||
return readyList.insert(i, mshr);
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
|
||||
MSHR *
|
||||
MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt)
|
||||
MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt,
|
||||
Tick when, Counter order)
|
||||
{
|
||||
assert(!freeList.empty());
|
||||
MSHR *mshr = freeList.front();
|
||||
assert(mshr->getNumTargets() == 0);
|
||||
freeList.pop_front();
|
||||
|
||||
mshr->allocate(addr, size, pkt);
|
||||
mshr->allocate(addr, size, pkt, when, order);
|
||||
mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
|
||||
mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
|
||||
mshr->readyIter = addToReadyList(mshr);
|
||||
|
||||
allocated += 1;
|
||||
return mshr;
|
||||
|
@ -139,7 +159,7 @@ MSHRQueue::deallocateOne(MSHR *mshr)
|
|||
if (mshr->inService) {
|
||||
inServiceEntries--;
|
||||
} else {
|
||||
pendingList.erase(mshr->readyIter);
|
||||
readyList.erase(mshr->readyIter);
|
||||
}
|
||||
mshr->deallocate();
|
||||
return retval;
|
||||
|
@ -150,14 +170,15 @@ MSHRQueue::moveToFront(MSHR *mshr)
|
|||
{
|
||||
if (!mshr->inService) {
|
||||
assert(mshr == *(mshr->readyIter));
|
||||
pendingList.erase(mshr->readyIter);
|
||||
mshr->readyIter = pendingList.insert(pendingList.begin(), mshr);
|
||||
readyList.erase(mshr->readyIter);
|
||||
mshr->readyIter = readyList.insert(readyList.begin(), mshr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MSHRQueue::markInService(MSHR *mshr)
|
||||
{
|
||||
assert(!mshr->inService);
|
||||
if (mshr->isSimpleForward()) {
|
||||
// we just forwarded the request packet & don't expect a
|
||||
// response, so get rid of it
|
||||
|
@ -167,23 +188,23 @@ MSHRQueue::markInService(MSHR *mshr)
|
|||
return;
|
||||
}
|
||||
mshr->inService = true;
|
||||
pendingList.erase(mshr->readyIter);
|
||||
readyList.erase(mshr->readyIter);
|
||||
//mshr->readyIter = NULL;
|
||||
inServiceEntries += 1;
|
||||
//pendingList.pop_front();
|
||||
//readyList.pop_front();
|
||||
}
|
||||
|
||||
void
|
||||
MSHRQueue::markPending(MSHR *mshr)
|
||||
{
|
||||
//assert(mshr->readyIter == NULL);
|
||||
assert(mshr->inService);
|
||||
mshr->inService = false;
|
||||
--inServiceEntries;
|
||||
/**
|
||||
* @ todo might want to add rerequests to front of pending list for
|
||||
* performance.
|
||||
*/
|
||||
mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
|
||||
mshr->readyIter = addToReadyList(mshr);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
23
src/mem/cache/miss/mshr_queue.hh
vendored
23
src/mem/cache/miss/mshr_queue.hh
vendored
|
@ -51,7 +51,7 @@ class MSHRQueue
|
|||
/** Holds pointers to all allocated entries. */
|
||||
MSHR::List allocatedList;
|
||||
/** Holds pointers to entries that haven't been sent to the bus. */
|
||||
MSHR::List pendingList;
|
||||
MSHR::List readyList;
|
||||
/** Holds non allocated entries. */
|
||||
MSHR::List freeList;
|
||||
|
||||
|
@ -69,6 +69,9 @@ class MSHRQueue
|
|||
*/
|
||||
const int numReserve;
|
||||
|
||||
MSHR::Iterator addToReadyList(MSHR *mshr);
|
||||
|
||||
|
||||
public:
|
||||
/** The number of allocated entries. */
|
||||
int allocated;
|
||||
|
@ -121,7 +124,8 @@ class MSHRQueue
|
|||
*
|
||||
* @pre There are free entries.
|
||||
*/
|
||||
MSHR *allocate(Addr addr, int size, PacketPtr &pkt);
|
||||
MSHR *allocate(Addr addr, int size, PacketPtr &pkt,
|
||||
Tick when, Counter order);
|
||||
|
||||
/**
|
||||
* Removes the given MSHR from the queue. This places the MSHR on the
|
||||
|
@ -147,7 +151,7 @@ class MSHRQueue
|
|||
|
||||
/**
|
||||
* Mark the given MSHR as in service. This removes the MSHR from the
|
||||
* pendingList. Deallocates the MSHR if it does not expect a response.
|
||||
* readyList. Deallocates the MSHR if it does not expect a response.
|
||||
* @param mshr The MSHR to mark in service.
|
||||
*/
|
||||
void markInService(MSHR *mshr);
|
||||
|
@ -171,7 +175,7 @@ class MSHRQueue
|
|||
*/
|
||||
bool havePending() const
|
||||
{
|
||||
return !pendingList.empty();
|
||||
return !readyList.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -184,15 +188,20 @@ class MSHRQueue
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the MSHR at the head of the pendingList.
|
||||
* Returns the MSHR at the head of the readyList.
|
||||
* @return The next request to service.
|
||||
*/
|
||||
MSHR *getNextMSHR() const
|
||||
{
|
||||
if (pendingList.empty()) {
|
||||
if (readyList.empty() || readyList.front()->readyTick > curTick) {
|
||||
return NULL;
|
||||
}
|
||||
return pendingList.front();
|
||||
return readyList.front();
|
||||
}
|
||||
|
||||
Tick nextMSHRReadyTick() const
|
||||
{
|
||||
return readyList.empty() ? MaxTick : readyList.front()->readyTick;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -91,28 +91,30 @@ SimpleTimingPort::schedSendTiming(PacketPtr pkt, Tick when)
|
|||
assert(when > curTick);
|
||||
|
||||
// Nothing is on the list: add it and schedule an event
|
||||
if (transmitList.empty()) {
|
||||
assert(!sendEvent->scheduled());
|
||||
sendEvent->schedule(when);
|
||||
transmitList.push_back(DeferredPacket(when, pkt));
|
||||
if (transmitList.empty() || when < transmitList.front().tick) {
|
||||
transmitList.push_front(DeferredPacket(when, pkt));
|
||||
schedSendEvent(when);
|
||||
return;
|
||||
}
|
||||
|
||||
// something is on the list and this belongs at the end
|
||||
// list is non-empty and this is not the head, so event should
|
||||
// already be scheduled
|
||||
assert(waitingOnRetry ||
|
||||
(sendEvent->scheduled() && sendEvent->when() <= when));
|
||||
|
||||
// list is non-empty & this belongs at the end
|
||||
if (when >= transmitList.back().tick) {
|
||||
transmitList.push_back(DeferredPacket(when, pkt));
|
||||
return;
|
||||
}
|
||||
// Something is on the list and this belongs somewhere else
|
||||
|
||||
// this belongs in the middle somewhere
|
||||
DeferredPacketIterator i = transmitList.begin();
|
||||
i++; // already checked for insertion at front
|
||||
DeferredPacketIterator end = transmitList.end();
|
||||
|
||||
for (; i != end; ++i) {
|
||||
if (when < i->tick) {
|
||||
if (i == transmitList.begin()) {
|
||||
//Inserting at begining, reschedule
|
||||
sendEvent->reschedule(when);
|
||||
}
|
||||
transmitList.insert(i, DeferredPacket(when, pkt));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -105,6 +105,24 @@ class SimpleTimingPort : public Port
|
|||
bool deferredPacketReady()
|
||||
{ return !transmitList.empty() && transmitList.front().tick <= curTick; }
|
||||
|
||||
Tick deferredPacketReadyTick()
|
||||
{ return transmitList.empty() ? MaxTick : transmitList.front().tick; }
|
||||
|
||||
void schedSendEvent(Tick when)
|
||||
{
|
||||
if (waitingOnRetry) {
|
||||
assert(!sendEvent->scheduled());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sendEvent->scheduled()) {
|
||||
sendEvent->schedule(when);
|
||||
} else if (sendEvent->when() > when) {
|
||||
sendEvent->reschedule(when);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Schedule a sendTiming() event to be called in the future.
|
||||
* @param pkt packet to send
|
||||
* @param absolute time (in ticks) to send packet
|
||||
|
|
Loading…
Reference in a new issue