Merge zizzer:/bk/newmem
into zazzer.eecs.umich.edu:/z/rdreslin/m5bk/newmemcleanest --HG-- extra : convert_revision : 498304c24435437f8f1942bb8aeafe69ba22a089
This commit is contained in:
commit
1d5d9c83b4
8 changed files with 297 additions and 63 deletions
92
src/mem/cache/base_cache.cc
vendored
92
src/mem/cache/base_cache.cc
vendored
|
@ -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);
|
||||||
|
|
139
src/mem/cache/base_cache.hh
vendored
139
src/mem/cache/base_cache.hh
vendored
|
@ -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++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
58
src/mem/cache/cache_impl.hh
vendored
58
src/mem/cache/cache_impl.hh
vendored
|
@ -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;
|
||||||
|
|
5
src/mem/cache/miss/mshr_queue.cc
vendored
5
src/mem/cache/miss/mshr_queue.cc
vendored
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue