summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRon Dreslinski <rdreslin@umich.edu>2006-11-12 10:41:18 -0500
committerRon Dreslinski <rdreslin@umich.edu>2006-11-12 10:41:18 -0500
commit1d5d9c83b416053ab94f17015b34f94de71ec146 (patch)
tree69059d13e1561f0e8e29d9e7de78b3019ebd7399 /src
parent8354cfc7151f4623aedee1e4b32157aa4c038707 (diff)
parent5edfaefc78c72540a17f65973118eec873019f17 (diff)
downloadgem5-1d5d9c83b416053ab94f17015b34f94de71ec146.tar.xz
Merge zizzer:/bk/newmem
into zazzer.eecs.umich.edu:/z/rdreslin/m5bk/newmemcleanest --HG-- extra : convert_revision : 498304c24435437f8f1942bb8aeafe69ba22a089
Diffstat (limited to 'src')
-rw-r--r--src/mem/cache/base_cache.cc92
-rw-r--r--src/mem/cache/base_cache.hh139
-rw-r--r--src/mem/cache/cache_impl.hh58
-rw-r--r--src/mem/cache/miss/mshr_queue.cc5
-rw-r--r--src/mem/packet.cc23
-rw-r--r--src/mem/packet.hh14
-rw-r--r--src/mem/physical.cc15
-rw-r--r--src/mem/tport.cc14
8 files changed, 297 insertions, 63 deletions
diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc
index c26d7782b..c16cb6945 100644
--- a/src/mem/cache/base_cache.cc
+++ b/src/mem/cache/base_cache.cc
@@ -102,21 +102,56 @@ BaseCache::CachePort::recvAtomic(PacketPtr pkt)
return cache->doAtomicAccess(pkt, isCpuSide);
}
-void
-BaseCache::CachePort::recvFunctional(PacketPtr pkt)
+bool
+BaseCache::CachePort::checkFunctional(PacketPtr pkt)
{
//Check storage here first
list<PacketPtr>::iterator i = drainList.begin();
- list<PacketPtr>::iterator end = drainList.end();
- for (; i != end; ++i) {
+ list<PacketPtr>::iterator iend = drainList.end();
+ bool notDone = true;
+ while (i != iend && notDone) {
PacketPtr target = *i;
// If the target contains data, and it overlaps the
// probed request, need to update data
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
@@ -135,7 +170,7 @@ BaseCache::CachePort::recvRetry()
isCpuSide && cache->doSlaveRequest()) {
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);
}
waitingOnRetry = false;
@@ -176,7 +211,7 @@ BaseCache::CachePort::recvRetry()
{
DPRINTF(CachePort, "%s has more requests\n", name());
//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);
}
}
@@ -194,7 +229,7 @@ BaseCache::CachePort::recvRetry()
{
DPRINTF(CachePort, "%s has more requests\n", name());
//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);
}
}
@@ -226,23 +261,19 @@ BaseCache::CachePort::clearBlocked()
}
}
-BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort)
- : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort)
+BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, bool _newResponse)
+ : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort),
+ newResponse(_newResponse)
{
- this->setFlags(AutoDelete);
+ if (!newResponse)
+ this->setFlags(AutoDelete);
pkt = NULL;
}
-BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, PacketPtr _pkt)
- : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort), pkt(_pkt)
-{
- this->setFlags(AutoDelete);
-}
-
void
BaseCache::CacheEvent::process()
{
- if (!pkt)
+ if (!newResponse)
{
if (cachePort->waitingOnRetry) return;
//We have some responses to drain first
@@ -322,8 +353,16 @@ BaseCache::CacheEvent::process()
}
return;
}
- //Response
- //Know the packet to send
+ //Else it's a response
+ 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)
pkt->result = Packet::Nacked;
else
@@ -343,7 +382,7 @@ BaseCache::CacheEvent::process()
}
// 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();
}
@@ -358,8 +397,10 @@ BaseCache::getPort(const std::string &if_name, int idx)
{
if (if_name == "")
{
- if(cpuSidePort == NULL)
+ if(cpuSidePort == NULL) {
cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true);
+ sendEvent = new CacheEvent(cpuSidePort, true);
+ }
return cpuSidePort;
}
else if (if_name == "functional")
@@ -368,8 +409,10 @@ BaseCache::getPort(const std::string &if_name, int idx)
}
else if (if_name == "cpu_side")
{
- if(cpuSidePort == NULL)
+ if(cpuSidePort == NULL) {
cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true);
+ sendEvent = new CacheEvent(cpuSidePort, true);
+ }
return cpuSidePort;
}
else if (if_name == "mem_side")
@@ -377,6 +420,7 @@ BaseCache::getPort(const std::string &if_name, int idx)
if (memSidePort != NULL)
panic("Already have a mem side for this cache\n");
memSidePort = new CachePort(name() + "-mem_side_port", this, false);
+ memSendEvent = new CacheEvent(memSidePort, true);
return memSidePort;
}
else panic("Port name %s unrecognized\n", if_name);
diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh
index ea7544fbb..584c2d5df 100644
--- a/src/mem/cache/base_cache.hh
+++ b/src/mem/cache/base_cache.hh
@@ -105,7 +105,11 @@ class BaseCache : public MemObject
void clearBlocked();
- bool canDrain() { return drainList.empty(); }
+ bool checkFunctional(PacketPtr pkt);
+
+ void checkAndSendFunctional(PacketPtr pkt);
+
+ bool canDrain() { return drainList.empty() && transmitList.empty(); }
bool blocked;
@@ -117,15 +121,16 @@ class BaseCache : public MemObject
std::list<PacketPtr> drainList;
+ std::list<std::pair<Tick,PacketPtr> > transmitList;
};
struct CacheEvent : public Event
{
CachePort *cachePort;
PacketPtr pkt;
+ bool newResponse;
- CacheEvent(CachePort *_cachePort);
- CacheEvent(CachePort *_cachePort, PacketPtr _pkt);
+ CacheEvent(CachePort *_cachePort, bool response);
void process();
const char *description();
};
@@ -133,6 +138,9 @@ class BaseCache : public MemObject
public: //Made public so coherence can get at it.
CachePort *cpuSidePort;
+ CacheEvent *sendEvent;
+ CacheEvent *memSendEvent;
+
protected:
CachePort *memSidePort;
@@ -353,6 +361,12 @@ class BaseCache : public MemObject
snoopRangesSent = false;
}
+ ~BaseCache()
+ {
+ delete sendEvent;
+ delete memSendEvent;
+ }
+
virtual void init();
/**
@@ -467,7 +481,8 @@ class BaseCache : public MemObject
{
if (!doMasterRequest() && !memSidePort->waitingOnRetry)
{
- BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(memSidePort);
+ BaseCache::CacheEvent * reqCpu =
+ new BaseCache::CacheEvent(memSidePort, false);
reqCpu->schedule(time);
}
uint8_t flag = 1<<cause;
@@ -503,7 +518,8 @@ class BaseCache : public MemObject
{
if (!doSlaveRequest() && !cpuSidePort->waitingOnRetry)
{
- BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(cpuSidePort);
+ BaseCache::CacheEvent * reqCpu =
+ new BaseCache::CacheEvent(cpuSidePort, false);
reqCpu->schedule(time);
}
uint8_t flag = 1<<cause;
@@ -528,9 +544,44 @@ class BaseCache : public MemObject
*/
void respond(PacketPtr pkt, Tick time)
{
+ assert(time >= curTick);
if (pkt->needsResponse()) {
- CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
+/* CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
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 {
if (pkt->cmd != Packet::UpgradeReq)
@@ -548,12 +599,48 @@ class BaseCache : public MemObject
*/
void respondToMiss(PacketPtr pkt, Tick time)
{
+ assert(time >= curTick);
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()) {
- CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
+/* CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
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 {
if (pkt->cmd != Packet::UpgradeReq)
@@ -570,9 +657,43 @@ class BaseCache : public MemObject
*/
void respondToSnoop(PacketPtr pkt, Tick time)
{
+ assert(time >= curTick);
assert (pkt->needsResponse());
- CacheEvent *reqMem = new CacheEvent(memSidePort, pkt);
+/* CacheEvent *reqMem = new CacheEvent(memSidePort, pkt);
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++;
+ }
}
/**
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh
index 9bb72e85c..df59b0a4f 100644
--- a/src/mem/cache/cache_impl.hh
+++ b/src/mem/cache/cache_impl.hh
@@ -53,6 +53,8 @@
#include "sim/sim_exit.hh" // for SimExitEvent
+bool SIGNAL_NACK_HACK;
+
template<class TagStore, class Buffering, class Coherence>
bool
Cache<TagStore,Buffering,Coherence>::
@@ -242,6 +244,11 @@ Cache<TagStore,Buffering,Coherence>::access(PacketPtr &pkt)
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;
}
@@ -265,6 +272,7 @@ Cache<TagStore,Buffering,Coherence>::getPacket()
assert(!doMasterRequest() || missQueue->havePending());
assert(!pkt || pkt->time <= curTick);
+ SIGNAL_NACK_HACK = false;
return pkt;
}
@@ -273,16 +281,15 @@ void
Cache<TagStore,Buffering,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr,
bool success)
{
- if (success && !(pkt && (pkt->flags & NACKED_LINE))) {
- if (!mshr->pkt->needsResponse()
- && !(mshr->pkt->cmd == Packet::UpgradeReq)
- && (pkt && (pkt->flags & SATISFIED))) {
- //Writeback, clean up the non copy version of the packet
- delete pkt;
- }
+ if (success && !(SIGNAL_NACK_HACK)) {
+ //Remember if it was an upgrade because writeback MSHR's are removed
+ //in Mark in Service
+ bool upgrade = (mshr->pkt && mshr->pkt->cmd == Packet::UpgradeReq);
+
missQueue->markInService(mshr->pkt, mshr);
+
//Temp Hack for UPGRADES
- if (mshr->pkt && mshr->pkt->cmd == Packet::UpgradeReq) {
+ if (upgrade) {
assert(pkt); //Upgrades need to be fixed
pkt->flags &= ~CACHE_LINE_FILL;
BlkType *blk = tags->findBlock(pkt);
@@ -300,6 +307,7 @@ Cache<TagStore,Buffering,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr,
}
} else if (pkt && !pkt->req->isUncacheable()) {
pkt->flags &= ~NACKED_LINE;
+ SIGNAL_NACK_HACK = false;
pkt->flags &= ~SATISFIED;
pkt->flags &= ~SNOOP_COMMIT;
@@ -333,6 +341,8 @@ Cache<TagStore,Buffering,Coherence>::handleResponse(PacketPtr &pkt)
DPRINTF(Cache, "Handling reponse to %x\n", pkt->getAddr());
if (pkt->isCacheFill() && !pkt->isNoAllocate()) {
+ DPRINTF(Cache, "Block for addr %x being updated in Cache\n",
+ pkt->getAddr());
blk = tags->findBlock(pkt);
CacheBlk::State old_state = (blk) ? blk->status : 0;
PacketList writebacks;
@@ -402,6 +412,7 @@ Cache<TagStore,Buffering,Coherence>::snoop(PacketPtr &pkt)
assert(!(pkt->flags & SATISFIED));
pkt->flags |= SATISFIED;
pkt->flags |= NACKED_LINE;
+ SIGNAL_NACK_HACK = true;
///@todo NACK's from other levels
//warn("NACKs from devices not connected to the same bus "
//"not implemented\n");
@@ -474,6 +485,13 @@ Cache<TagStore,Buffering,Coherence>::snoop(PacketPtr &pkt)
}
CacheBlk::State 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) {
DPRINTF(Cache, "Cache snooped a %s request for addr %x and "
"now supplying data, new state is %i\n",
@@ -486,6 +504,7 @@ Cache<TagStore,Buffering,Coherence>::snoop(PacketPtr &pkt)
if (blk)
DPRINTF(Cache, "Cache snooped a %s request for addr %x, "
"new state is %i\n", pkt->cmdString(), blk_addr, 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.
- otherSidePort->sendFunctional(pkt);
+ otherSidePort->checkAndSendFunctional(pkt);
if (pkt->isRead() && pkt->result == Packet::Success)
return 0;
}
@@ -560,30 +579,33 @@ Cache<TagStore,Buffering,Coherence>::probe(PacketPtr &pkt, bool update,
missQueue->findWrites(blk_addr, writes);
if (!update) {
+ bool notDone = !(pkt->flags & SATISFIED); //Hit in cache (was a block)
// Check for data in MSHR and writebuffer.
if (mshr) {
MSHR::TargetList *targets = mshr->getTargetList();
MSHR::TargetList::iterator i = targets->begin();
MSHR::TargetList::iterator end = targets->end();
- for (; i != end; ++i) {
+ for (; i != end && notDone; ++i) {
PacketPtr target = *i;
// If the target contains data, and it overlaps the
// probed request, need to update data
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;
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()
- && pkt->result != Packet::Success
- && otherSidePort == memSidePort) {
- otherSidePort->sendFunctional(pkt);
+ if (notDone && otherSidePort == memSidePort) {
+ otherSidePort->checkAndSendFunctional(pkt);
assert(pkt->result == Packet::Success);
}
return 0;
diff --git a/src/mem/cache/miss/mshr_queue.cc b/src/mem/cache/miss/mshr_queue.cc
index d3a7a7933..6cb62429d 100644
--- a/src/mem/cache/miss/mshr_queue.cc
+++ b/src/mem/cache/miss/mshr_queue.cc
@@ -198,11 +198,6 @@ MSHRQueue::markInService(MSHR* mshr)
//assert(mshr == pendingList.front());
if (!mshr->pkt->needsResponse() && !(mshr->pkt->cmd == Packet::UpgradeReq)) {
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);
return;
}
diff --git a/src/mem/packet.cc b/src/mem/packet.cc
index a342af634..e2faf4527 100644
--- a/src/mem/packet.cc
+++ b/src/mem/packet.cc
@@ -144,6 +144,24 @@ Packet::intersect(PacketPtr p)
}
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
fixPacket(PacketPtr func, PacketPtr timing)
{
Addr funcStart = func->getAddr();
@@ -168,6 +186,7 @@ fixPacket(PacketPtr func, PacketPtr timing)
memcpy(func->getPtr<uint8_t>(), timing->getPtr<uint8_t>() +
funcStart - timingStart, func->getSize());
func->result = Packet::Success;
+ func->flags |= SATISFIED;
return false;
} else {
// In this case the timing packet only partially satisfies the
@@ -182,11 +201,11 @@ fixPacket(PacketPtr func, PacketPtr timing)
if (funcStart >= timingStart) {
memcpy(timing->getPtr<uint8_t>() + (funcStart - timingStart),
func->getPtr<uint8_t>(),
- std::min(funcEnd, timingEnd) - funcStart);
+ (std::min(funcEnd, timingEnd) - funcStart) + 1);
} else { // timingStart > funcStart
memcpy(timing->getPtr<uint8_t>(),
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
return true;
diff --git a/src/mem/packet.hh b/src/mem/packet.hh
index cb97dd036..2bc51bf12 100644
--- a/src/mem/packet.hh
+++ b/src/mem/packet.hh
@@ -344,6 +344,13 @@ class Packet
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
* returning as a response to that request.
@@ -448,7 +455,6 @@ class Packet
bool intersect(PacketPtr p);
};
-
/** 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
* 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);
+/** 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);
#endif //__MEM_PACKET_HH
diff --git a/src/mem/physical.cc b/src/mem/physical.cc
index 39eb63108..94f60ad80 100644
--- a/src/mem/physical.cc
+++ b/src/mem/physical.cc
@@ -288,6 +288,21 @@ PhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt)
void
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()
// calls recvAtomic() and throws away the latency; we can save a
// little here by just not calculating the latency.
diff --git a/src/mem/tport.cc b/src/mem/tport.cc
index 086d91279..c43c9aac0 100644
--- a/src/mem/tport.cc
+++ b/src/mem/tport.cc
@@ -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 end = transmitList.end();
- bool done = false;
+ bool notDone = true;
- while (i != end && !done) {
+ 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))
- done = fixPacket(pkt, target);
+ notDone = fixPacket(pkt, target);
i++;
}
@@ -118,8 +118,14 @@ SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time)
bool done = false;
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));
+ done = true;
+ }
i++;
}
}