Merge zizzer:/bk/newmem

into  zazzer.eecs.umich.edu:/z/rdreslin/m5bk/newmemcleanest

--HG--
extra : convert_revision : 498304c24435437f8f1942bb8aeafe69ba22a089
This commit is contained in:
Ron Dreslinski 2006-11-12 10:41:18 -05:00
commit 1d5d9c83b4
8 changed files with 297 additions and 63 deletions

View file

@ -102,21 +102,56 @@ BaseCache::CachePort::recvAtomic(PacketPtr pkt)
return cache->doAtomicAccess(pkt, isCpuSide); return cache->doAtomicAccess(pkt, isCpuSide);
} }
void bool
BaseCache::CachePort::recvFunctional(PacketPtr pkt) BaseCache::CachePort::checkFunctional(PacketPtr pkt)
{ {
//Check storage here first //Check storage here first
list<PacketPtr>::iterator i = drainList.begin(); list<PacketPtr>::iterator i = drainList.begin();
list<PacketPtr>::iterator end = drainList.end(); list<PacketPtr>::iterator iend = drainList.end();
for (; i != end; ++i) { bool notDone = true;
while (i != iend && notDone) {
PacketPtr target = *i; PacketPtr target = *i;
// If the target contains data, and it overlaps the // If the target contains data, and it overlaps the
// probed request, need to update data // probed request, need to update data
if (target->intersect(pkt)) { if (target->intersect(pkt)) {
fixPacket(pkt, target); DPRINTF(Cache, "Functional %s access to blk_addr %x intersects a drain\n",
pkt->cmdString(), pkt->getAddr() & ~(cache->getBlockSize() - 1));
notDone = fixPacket(pkt, target);
} }
i++;
} }
cache->doFunctionalAccess(pkt, isCpuSide); //Also check the response not yet ready to be on the list
std::list<std::pair<Tick,PacketPtr> >::iterator j = transmitList.begin();
std::list<std::pair<Tick,PacketPtr> >::iterator jend = transmitList.end();
while (j != jend && notDone) {
PacketPtr target = j->second;
// If the target contains data, and it overlaps the
// probed request, need to update data
if (target->intersect(pkt)) {
DPRINTF(Cache, "Functional %s access to blk_addr %x intersects a response\n",
pkt->cmdString(), pkt->getAddr() & ~(cache->getBlockSize() - 1));
notDone = fixDelayedResponsePacket(pkt, target);
}
j++;
}
return notDone;
}
void
BaseCache::CachePort::recvFunctional(PacketPtr pkt)
{
bool notDone = checkFunctional(pkt);
if (notDone)
cache->doFunctionalAccess(pkt, isCpuSide);
}
void
BaseCache::CachePort::checkAndSendFunctional(PacketPtr pkt)
{
bool notDone = checkFunctional(pkt);
if (notDone)
sendFunctional(pkt);
} }
void void
@ -135,7 +170,7 @@ BaseCache::CachePort::recvRetry()
isCpuSide && cache->doSlaveRequest()) { isCpuSide && cache->doSlaveRequest()) {
DPRINTF(CachePort, "%s has more responses/requests\n", name()); DPRINTF(CachePort, "%s has more responses/requests\n", name());
BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this); BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this, false);
reqCpu->schedule(curTick + 1); reqCpu->schedule(curTick + 1);
} }
waitingOnRetry = false; waitingOnRetry = false;
@ -176,7 +211,7 @@ BaseCache::CachePort::recvRetry()
{ {
DPRINTF(CachePort, "%s has more requests\n", name()); DPRINTF(CachePort, "%s has more requests\n", name());
//Still more to issue, rerequest in 1 cycle //Still more to issue, rerequest in 1 cycle
BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this); BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this, false);
reqCpu->schedule(curTick + 1); reqCpu->schedule(curTick + 1);
} }
} }
@ -194,7 +229,7 @@ BaseCache::CachePort::recvRetry()
{ {
DPRINTF(CachePort, "%s has more requests\n", name()); DPRINTF(CachePort, "%s has more requests\n", name());
//Still more to issue, rerequest in 1 cycle //Still more to issue, rerequest in 1 cycle
BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this); BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this, false);
reqCpu->schedule(curTick + 1); reqCpu->schedule(curTick + 1);
} }
} }
@ -226,23 +261,19 @@ BaseCache::CachePort::clearBlocked()
} }
} }
BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort) BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, bool _newResponse)
: Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort) : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort),
newResponse(_newResponse)
{ {
this->setFlags(AutoDelete); if (!newResponse)
this->setFlags(AutoDelete);
pkt = NULL; pkt = NULL;
} }
BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, PacketPtr _pkt)
: Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort), pkt(_pkt)
{
this->setFlags(AutoDelete);
}
void void
BaseCache::CacheEvent::process() BaseCache::CacheEvent::process()
{ {
if (!pkt) if (!newResponse)
{ {
if (cachePort->waitingOnRetry) return; if (cachePort->waitingOnRetry) return;
//We have some responses to drain first //We have some responses to drain first
@ -322,8 +353,16 @@ BaseCache::CacheEvent::process()
} }
return; return;
} }
//Response //Else it's a response
//Know the packet to send assert(cachePort->transmitList.size());
assert(cachePort->transmitList.front().first <= curTick);
pkt = cachePort->transmitList.front().second;
cachePort->transmitList.pop_front();
if (!cachePort->transmitList.empty()) {
Tick time = cachePort->transmitList.front().first;
schedule(time <= curTick ? curTick+1 : time);
}
if (pkt->flags & NACKED_LINE) if (pkt->flags & NACKED_LINE)
pkt->result = Packet::Nacked; pkt->result = Packet::Nacked;
else else
@ -343,7 +382,7 @@ BaseCache::CacheEvent::process()
} }
// Check if we're done draining once this list is empty // Check if we're done draining once this list is empty
if (cachePort->drainList.empty()) if (cachePort->drainList.empty() && cachePort->transmitList.empty())
cachePort->cache->checkDrain(); cachePort->cache->checkDrain();
} }
@ -358,8 +397,10 @@ BaseCache::getPort(const std::string &if_name, int idx)
{ {
if (if_name == "") if (if_name == "")
{ {
if(cpuSidePort == NULL) if(cpuSidePort == NULL) {
cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true);
sendEvent = new CacheEvent(cpuSidePort, true);
}
return cpuSidePort; return cpuSidePort;
} }
else if (if_name == "functional") else if (if_name == "functional")
@ -368,8 +409,10 @@ BaseCache::getPort(const std::string &if_name, int idx)
} }
else if (if_name == "cpu_side") else if (if_name == "cpu_side")
{ {
if(cpuSidePort == NULL) if(cpuSidePort == NULL) {
cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true);
sendEvent = new CacheEvent(cpuSidePort, true);
}
return cpuSidePort; return cpuSidePort;
} }
else if (if_name == "mem_side") else if (if_name == "mem_side")
@ -377,6 +420,7 @@ BaseCache::getPort(const std::string &if_name, int idx)
if (memSidePort != NULL) if (memSidePort != NULL)
panic("Already have a mem side for this cache\n"); panic("Already have a mem side for this cache\n");
memSidePort = new CachePort(name() + "-mem_side_port", this, false); memSidePort = new CachePort(name() + "-mem_side_port", this, false);
memSendEvent = new CacheEvent(memSidePort, true);
return memSidePort; return memSidePort;
} }
else panic("Port name %s unrecognized\n", if_name); else panic("Port name %s unrecognized\n", if_name);

View file

@ -105,7 +105,11 @@ class BaseCache : public MemObject
void clearBlocked(); void clearBlocked();
bool canDrain() { return drainList.empty(); } bool checkFunctional(PacketPtr pkt);
void checkAndSendFunctional(PacketPtr pkt);
bool canDrain() { return drainList.empty() && transmitList.empty(); }
bool blocked; bool blocked;
@ -117,15 +121,16 @@ class BaseCache : public MemObject
std::list<PacketPtr> drainList; std::list<PacketPtr> drainList;
std::list<std::pair<Tick,PacketPtr> > transmitList;
}; };
struct CacheEvent : public Event struct CacheEvent : public Event
{ {
CachePort *cachePort; CachePort *cachePort;
PacketPtr pkt; PacketPtr pkt;
bool newResponse;
CacheEvent(CachePort *_cachePort); CacheEvent(CachePort *_cachePort, bool response);
CacheEvent(CachePort *_cachePort, PacketPtr _pkt);
void process(); void process();
const char *description(); const char *description();
}; };
@ -133,6 +138,9 @@ class BaseCache : public MemObject
public: //Made public so coherence can get at it. public: //Made public so coherence can get at it.
CachePort *cpuSidePort; CachePort *cpuSidePort;
CacheEvent *sendEvent;
CacheEvent *memSendEvent;
protected: protected:
CachePort *memSidePort; CachePort *memSidePort;
@ -353,6 +361,12 @@ class BaseCache : public MemObject
snoopRangesSent = false; snoopRangesSent = false;
} }
~BaseCache()
{
delete sendEvent;
delete memSendEvent;
}
virtual void init(); virtual void init();
/** /**
@ -467,7 +481,8 @@ class BaseCache : public MemObject
{ {
if (!doMasterRequest() && !memSidePort->waitingOnRetry) if (!doMasterRequest() && !memSidePort->waitingOnRetry)
{ {
BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(memSidePort); BaseCache::CacheEvent * reqCpu =
new BaseCache::CacheEvent(memSidePort, false);
reqCpu->schedule(time); reqCpu->schedule(time);
} }
uint8_t flag = 1<<cause; uint8_t flag = 1<<cause;
@ -503,7 +518,8 @@ class BaseCache : public MemObject
{ {
if (!doSlaveRequest() && !cpuSidePort->waitingOnRetry) if (!doSlaveRequest() && !cpuSidePort->waitingOnRetry)
{ {
BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(cpuSidePort); BaseCache::CacheEvent * reqCpu =
new BaseCache::CacheEvent(cpuSidePort, false);
reqCpu->schedule(time); reqCpu->schedule(time);
} }
uint8_t flag = 1<<cause; uint8_t flag = 1<<cause;
@ -528,9 +544,44 @@ class BaseCache : public MemObject
*/ */
void respond(PacketPtr pkt, Tick time) void respond(PacketPtr pkt, Tick time)
{ {
assert(time >= curTick);
if (pkt->needsResponse()) { if (pkt->needsResponse()) {
CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt); /* CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
reqCpu->schedule(time); reqCpu->schedule(time);
*/
if (cpuSidePort->transmitList.empty()) {
assert(!sendEvent->scheduled());
sendEvent->schedule(time);
cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
(time,pkt));
return;
}
// something is on the list and this belongs at the end
if (time >= cpuSidePort->transmitList.back().first) {
cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
(time,pkt));
return;
}
// Something is on the list and this belongs somewhere else
std::list<std::pair<Tick,PacketPtr> >::iterator i =
cpuSidePort->transmitList.begin();
std::list<std::pair<Tick,PacketPtr> >::iterator end =
cpuSidePort->transmitList.end();
bool done = false;
while (i != end && !done) {
if (time < i->first) {
if (i == cpuSidePort->transmitList.begin()) {
//Inserting at begining, reschedule
sendEvent->reschedule(time);
}
cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>
(time,pkt));
done = true;
}
i++;
}
} }
else { else {
if (pkt->cmd != Packet::UpgradeReq) if (pkt->cmd != Packet::UpgradeReq)
@ -548,12 +599,48 @@ class BaseCache : public MemObject
*/ */
void respondToMiss(PacketPtr pkt, Tick time) void respondToMiss(PacketPtr pkt, Tick time)
{ {
assert(time >= curTick);
if (!pkt->req->isUncacheable()) { if (!pkt->req->isUncacheable()) {
missLatency[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] += time - pkt->time; missLatency[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] +=
time - pkt->time;
} }
if (pkt->needsResponse()) { if (pkt->needsResponse()) {
CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt); /* CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
reqCpu->schedule(time); reqCpu->schedule(time);
*/
if (cpuSidePort->transmitList.empty()) {
assert(!sendEvent->scheduled());
sendEvent->schedule(time);
cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
(time,pkt));
return;
}
// something is on the list and this belongs at the end
if (time >= cpuSidePort->transmitList.back().first) {
cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
(time,pkt));
return;
}
// Something is on the list and this belongs somewhere else
std::list<std::pair<Tick,PacketPtr> >::iterator i =
cpuSidePort->transmitList.begin();
std::list<std::pair<Tick,PacketPtr> >::iterator end =
cpuSidePort->transmitList.end();
bool done = false;
while (i != end && !done) {
if (time < i->first) {
if (i == cpuSidePort->transmitList.begin()) {
//Inserting at begining, reschedule
sendEvent->reschedule(time);
}
cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>
(time,pkt));
done = true;
}
i++;
}
} }
else { else {
if (pkt->cmd != Packet::UpgradeReq) if (pkt->cmd != Packet::UpgradeReq)
@ -570,9 +657,43 @@ class BaseCache : public MemObject
*/ */
void respondToSnoop(PacketPtr pkt, Tick time) void respondToSnoop(PacketPtr pkt, Tick time)
{ {
assert(time >= curTick);
assert (pkt->needsResponse()); assert (pkt->needsResponse());
CacheEvent *reqMem = new CacheEvent(memSidePort, pkt); /* CacheEvent *reqMem = new CacheEvent(memSidePort, pkt);
reqMem->schedule(time); reqMem->schedule(time);
*/
if (memSidePort->transmitList.empty()) {
assert(!memSendEvent->scheduled());
memSendEvent->schedule(time);
memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
(time,pkt));
return;
}
// something is on the list and this belongs at the end
if (time >= memSidePort->transmitList.back().first) {
memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
(time,pkt));
return;
}
// Something is on the list and this belongs somewhere else
std::list<std::pair<Tick,PacketPtr> >::iterator i =
memSidePort->transmitList.begin();
std::list<std::pair<Tick,PacketPtr> >::iterator end =
memSidePort->transmitList.end();
bool done = false;
while (i != end && !done) {
if (time < i->first) {
if (i == memSidePort->transmitList.begin()) {
//Inserting at begining, reschedule
memSendEvent->reschedule(time);
}
memSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>(time,pkt));
done = true;
}
i++;
}
} }
/** /**

View file

@ -53,6 +53,8 @@
#include "sim/sim_exit.hh" // for SimExitEvent #include "sim/sim_exit.hh" // for SimExitEvent
bool SIGNAL_NACK_HACK;
template<class TagStore, class Buffering, class Coherence> template<class TagStore, class Buffering, class Coherence>
bool bool
Cache<TagStore,Buffering,Coherence>:: Cache<TagStore,Buffering,Coherence>::
@ -242,6 +244,11 @@ Cache<TagStore,Buffering,Coherence>::access(PacketPtr &pkt)
missQueue->handleMiss(pkt, size, curTick + hitLatency); missQueue->handleMiss(pkt, size, curTick + hitLatency);
} }
if (pkt->cmd == Packet::Writeback) {
//Need to clean up the packet on a writeback miss, but leave the request
delete pkt;
}
return true; return true;
} }
@ -265,6 +272,7 @@ Cache<TagStore,Buffering,Coherence>::getPacket()
assert(!doMasterRequest() || missQueue->havePending()); assert(!doMasterRequest() || missQueue->havePending());
assert(!pkt || pkt->time <= curTick); assert(!pkt || pkt->time <= curTick);
SIGNAL_NACK_HACK = false;
return pkt; return pkt;
} }
@ -273,16 +281,15 @@ void
Cache<TagStore,Buffering,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr, Cache<TagStore,Buffering,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr,
bool success) bool success)
{ {
if (success && !(pkt && (pkt->flags & NACKED_LINE))) { if (success && !(SIGNAL_NACK_HACK)) {
if (!mshr->pkt->needsResponse() //Remember if it was an upgrade because writeback MSHR's are removed
&& !(mshr->pkt->cmd == Packet::UpgradeReq) //in Mark in Service
&& (pkt && (pkt->flags & SATISFIED))) { bool upgrade = (mshr->pkt && mshr->pkt->cmd == Packet::UpgradeReq);
//Writeback, clean up the non copy version of the packet
delete pkt;
}
missQueue->markInService(mshr->pkt, mshr); missQueue->markInService(mshr->pkt, mshr);
//Temp Hack for UPGRADES //Temp Hack for UPGRADES
if (mshr->pkt && mshr->pkt->cmd == Packet::UpgradeReq) { if (upgrade) {
assert(pkt); //Upgrades need to be fixed assert(pkt); //Upgrades need to be fixed
pkt->flags &= ~CACHE_LINE_FILL; pkt->flags &= ~CACHE_LINE_FILL;
BlkType *blk = tags->findBlock(pkt); BlkType *blk = tags->findBlock(pkt);
@ -300,6 +307,7 @@ Cache<TagStore,Buffering,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr,
} }
} else if (pkt && !pkt->req->isUncacheable()) { } else if (pkt && !pkt->req->isUncacheable()) {
pkt->flags &= ~NACKED_LINE; pkt->flags &= ~NACKED_LINE;
SIGNAL_NACK_HACK = false;
pkt->flags &= ~SATISFIED; pkt->flags &= ~SATISFIED;
pkt->flags &= ~SNOOP_COMMIT; pkt->flags &= ~SNOOP_COMMIT;
@ -333,6 +341,8 @@ Cache<TagStore,Buffering,Coherence>::handleResponse(PacketPtr &pkt)
DPRINTF(Cache, "Handling reponse to %x\n", pkt->getAddr()); DPRINTF(Cache, "Handling reponse to %x\n", pkt->getAddr());
if (pkt->isCacheFill() && !pkt->isNoAllocate()) { if (pkt->isCacheFill() && !pkt->isNoAllocate()) {
DPRINTF(Cache, "Block for addr %x being updated in Cache\n",
pkt->getAddr());
blk = tags->findBlock(pkt); blk = tags->findBlock(pkt);
CacheBlk::State old_state = (blk) ? blk->status : 0; CacheBlk::State old_state = (blk) ? blk->status : 0;
PacketList writebacks; PacketList writebacks;
@ -402,6 +412,7 @@ Cache<TagStore,Buffering,Coherence>::snoop(PacketPtr &pkt)
assert(!(pkt->flags & SATISFIED)); assert(!(pkt->flags & SATISFIED));
pkt->flags |= SATISFIED; pkt->flags |= SATISFIED;
pkt->flags |= NACKED_LINE; pkt->flags |= NACKED_LINE;
SIGNAL_NACK_HACK = true;
///@todo NACK's from other levels ///@todo NACK's from other levels
//warn("NACKs from devices not connected to the same bus " //warn("NACKs from devices not connected to the same bus "
//"not implemented\n"); //"not implemented\n");
@ -474,6 +485,13 @@ Cache<TagStore,Buffering,Coherence>::snoop(PacketPtr &pkt)
} }
CacheBlk::State new_state; CacheBlk::State new_state;
bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state); bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state);
if (blk && mshr && !mshr->inService && new_state == 0) {
//There was a outstanding write to a shared block, not need ReadEx
//not update, so change No Allocate param in MSHR
mshr->pkt->flags &= ~NO_ALLOCATE;
}
if (satisfy) { if (satisfy) {
DPRINTF(Cache, "Cache snooped a %s request for addr %x and " DPRINTF(Cache, "Cache snooped a %s request for addr %x and "
"now supplying data, new state is %i\n", "now supplying data, new state is %i\n",
@ -486,6 +504,7 @@ Cache<TagStore,Buffering,Coherence>::snoop(PacketPtr &pkt)
if (blk) if (blk)
DPRINTF(Cache, "Cache snooped a %s request for addr %x, " DPRINTF(Cache, "Cache snooped a %s request for addr %x, "
"new state is %i\n", pkt->cmdString(), blk_addr, new_state); "new state is %i\n", pkt->cmdString(), blk_addr, new_state);
tags->handleSnoop(blk, new_state); tags->handleSnoop(blk, new_state);
} }
@ -534,9 +553,9 @@ Cache<TagStore,Buffering,Coherence>::probe(PacketPtr &pkt, bool update,
} }
} }
if (!update && (pkt->isWrite() || (otherSidePort == cpuSidePort))) { if (!update && (otherSidePort == cpuSidePort)) {
// Still need to change data in all locations. // Still need to change data in all locations.
otherSidePort->sendFunctional(pkt); otherSidePort->checkAndSendFunctional(pkt);
if (pkt->isRead() && pkt->result == Packet::Success) if (pkt->isRead() && pkt->result == Packet::Success)
return 0; return 0;
} }
@ -560,30 +579,33 @@ Cache<TagStore,Buffering,Coherence>::probe(PacketPtr &pkt, bool update,
missQueue->findWrites(blk_addr, writes); missQueue->findWrites(blk_addr, writes);
if (!update) { if (!update) {
bool notDone = !(pkt->flags & SATISFIED); //Hit in cache (was a block)
// Check for data in MSHR and writebuffer. // Check for data in MSHR and writebuffer.
if (mshr) { if (mshr) {
MSHR::TargetList *targets = mshr->getTargetList(); MSHR::TargetList *targets = mshr->getTargetList();
MSHR::TargetList::iterator i = targets->begin(); MSHR::TargetList::iterator i = targets->begin();
MSHR::TargetList::iterator end = targets->end(); MSHR::TargetList::iterator end = targets->end();
for (; i != end; ++i) { for (; i != end && notDone; ++i) {
PacketPtr target = *i; PacketPtr target = *i;
// If the target contains data, and it overlaps the // If the target contains data, and it overlaps the
// probed request, need to update data // probed request, need to update data
if (target->intersect(pkt)) { if (target->intersect(pkt)) {
fixPacket(pkt, target); DPRINTF(Cache, "Functional %s access to blk_addr %x intersects a MSHR\n",
pkt->cmdString(), blk_addr);
notDone = fixPacket(pkt, target);
} }
} }
} }
for (int i = 0; i < writes.size(); ++i) { for (int i = 0; i < writes.size() && notDone; ++i) {
PacketPtr write = writes[i]->pkt; PacketPtr write = writes[i]->pkt;
if (write->intersect(pkt)) { if (write->intersect(pkt)) {
fixPacket(pkt, write); DPRINTF(Cache, "Functional %s access to blk_addr %x intersects a writeback\n",
pkt->cmdString(), blk_addr);
notDone = fixPacket(pkt, write);
} }
} }
if (pkt->isRead() if (notDone && otherSidePort == memSidePort) {
&& pkt->result != Packet::Success otherSidePort->checkAndSendFunctional(pkt);
&& otherSidePort == memSidePort) {
otherSidePort->sendFunctional(pkt);
assert(pkt->result == Packet::Success); assert(pkt->result == Packet::Success);
} }
return 0; return 0;

View file

@ -198,11 +198,6 @@ MSHRQueue::markInService(MSHR* mshr)
//assert(mshr == pendingList.front()); //assert(mshr == pendingList.front());
if (!mshr->pkt->needsResponse() && !(mshr->pkt->cmd == Packet::UpgradeReq)) { if (!mshr->pkt->needsResponse() && !(mshr->pkt->cmd == Packet::UpgradeReq)) {
assert(mshr->getNumTargets() == 0); assert(mshr->getNumTargets() == 0);
if ((mshr->pkt->flags & SATISFIED) && (mshr->pkt->cmd == Packet::Writeback)) {
//Writeback hit, so delete it
//otherwise the consumer will delete it
delete mshr->pkt->req;
}
deallocate(mshr); deallocate(mshr);
return; return;
} }

View file

@ -143,6 +143,24 @@ Packet::intersect(PacketPtr p)
return !(s1 > e2 || e1 < s2); return !(s1 > e2 || e1 < s2);
} }
bool
fixDelayedResponsePacket(PacketPtr func, PacketPtr timing)
{
bool result;
if (timing->isRead() || timing->isWrite()) {
timing->toggleData();
result = fixPacket(func, timing);
timing->toggleData();
}
else {
//Don't toggle if it isn't a read/write response
result = fixPacket(func, timing);
}
return result;
}
bool bool
fixPacket(PacketPtr func, PacketPtr timing) fixPacket(PacketPtr func, PacketPtr timing)
{ {
@ -168,6 +186,7 @@ fixPacket(PacketPtr func, PacketPtr timing)
memcpy(func->getPtr<uint8_t>(), timing->getPtr<uint8_t>() + memcpy(func->getPtr<uint8_t>(), timing->getPtr<uint8_t>() +
funcStart - timingStart, func->getSize()); funcStart - timingStart, func->getSize());
func->result = Packet::Success; func->result = Packet::Success;
func->flags |= SATISFIED;
return false; return false;
} else { } else {
// In this case the timing packet only partially satisfies the // In this case the timing packet only partially satisfies the
@ -182,11 +201,11 @@ fixPacket(PacketPtr func, PacketPtr timing)
if (funcStart >= timingStart) { if (funcStart >= timingStart) {
memcpy(timing->getPtr<uint8_t>() + (funcStart - timingStart), memcpy(timing->getPtr<uint8_t>() + (funcStart - timingStart),
func->getPtr<uint8_t>(), func->getPtr<uint8_t>(),
std::min(funcEnd, timingEnd) - funcStart); (std::min(funcEnd, timingEnd) - funcStart) + 1);
} else { // timingStart > funcStart } else { // timingStart > funcStart
memcpy(timing->getPtr<uint8_t>(), memcpy(timing->getPtr<uint8_t>(),
func->getPtr<uint8_t>() + (timingStart - funcStart), func->getPtr<uint8_t>() + (timingStart - funcStart),
std::min(funcEnd, timingEnd) - timingStart); (std::min(funcEnd, timingEnd) - timingStart) + 1);
} }
// we always want to keep going with a write // we always want to keep going with a write
return true; return true;

View file

@ -344,6 +344,13 @@ class Packet
srcValid = false; srcValid = false;
} }
void toggleData() {
int icmd = (int)cmd;
icmd ^= HasData;
cmd = (Command)icmd;
}
/** /**
* Take a request packet and modify it in place to be suitable for * Take a request packet and modify it in place to be suitable for
* returning as a response to that request. * returning as a response to that request.
@ -448,7 +455,6 @@ class Packet
bool intersect(PacketPtr p); bool intersect(PacketPtr p);
}; };
/** This function given a functional packet and a timing packet either satisfies /** This function given a functional packet and a timing packet either satisfies
* the timing packet, or updates the timing packet to reflect the updated state * the timing packet, or updates the timing packet to reflect the updated state
* in the timing packet. It returns if the functional packet should continue to * in the timing packet. It returns if the functional packet should continue to
@ -456,6 +462,12 @@ class Packet
*/ */
bool fixPacket(PacketPtr func, PacketPtr timing); bool fixPacket(PacketPtr func, PacketPtr timing);
/** This function is a wrapper for the fixPacket field that toggles the hasData bit
* it is used when a response is waiting in the caches, but hasn't been marked as a
* response yet (so the fixPacket needs to get the correct value for the hasData)
*/
bool fixDelayedResponsePacket(PacketPtr func, PacketPtr timing);
std::ostream & operator<<(std::ostream &o, const Packet &p); std::ostream & operator<<(std::ostream &o, const Packet &p);
#endif //__MEM_PACKET_HH #endif //__MEM_PACKET_HH

View file

@ -288,6 +288,21 @@ PhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt)
void void
PhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) PhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt)
{ {
//Since we are overriding the function, make sure to have the impl of the
//check or functional accesses here.
std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin();
std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end();
bool notDone = true;
while (i != end && notDone) {
PacketPtr target = i->second;
// If the target contains data, and it overlaps the
// probed request, need to update data
if (target->intersect(pkt))
notDone = fixPacket(pkt, target);
i++;
}
// Default implementation of SimpleTimingPort::recvFunctional() // Default implementation of SimpleTimingPort::recvFunctional()
// calls recvAtomic() and throws away the latency; we can save a // calls recvAtomic() and throws away the latency; we can save a
// little here by just not calculating the latency. // little here by just not calculating the latency.

View file

@ -35,14 +35,14 @@ SimpleTimingPort::recvFunctional(PacketPtr pkt)
{ {
std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin(); std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin();
std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end(); std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end();
bool done = false; bool notDone = true;
while (i != end && !done) { while (i != end && notDone) {
PacketPtr target = i->second; PacketPtr target = i->second;
// If the target contains data, and it overlaps the // If the target contains data, and it overlaps the
// probed request, need to update data // probed request, need to update data
if (target->intersect(pkt)) if (target->intersect(pkt))
done = fixPacket(pkt, target); notDone = fixPacket(pkt, target);
i++; i++;
} }
@ -118,8 +118,14 @@ SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time)
bool done = false; bool done = false;
while (i != end && !done) { while (i != end && !done) {
if (time+curTick < i->first) if (time+curTick < i->first) {
if (i == transmitList.begin()) {
//Inserting at begining, reschedule
sendEvent.reschedule(time+curTick);
}
transmitList.insert(i,std::pair<Tick,PacketPtr>(time+curTick,pkt)); transmitList.insert(i,std::pair<Tick,PacketPtr>(time+curTick,pkt));
done = true;
}
i++; i++;
} }
} }