#include "sim/sim_exit.hh" // for SimExitEvent
+bool SIGNAL_NACK_HACK;
+
template<class TagStore, class Buffering, class Coherence>
bool
Cache<TagStore,Buffering,Coherence>::
-doTimingAccess(Packet *pkt, CachePort *cachePort, bool isCpuSide)
+doTimingAccess(PacketPtr pkt, CachePort *cachePort, bool isCpuSide)
{
if (isCpuSide)
{
template<class TagStore, class Buffering, class Coherence>
Tick
Cache<TagStore,Buffering,Coherence>::
-doAtomicAccess(Packet *pkt, bool isCpuSide)
+doAtomicAccess(PacketPtr pkt, bool isCpuSide)
{
if (isCpuSide)
{
template<class TagStore, class Buffering, class Coherence>
void
Cache<TagStore,Buffering,Coherence>::
-doFunctionalAccess(Packet *pkt, bool isCpuSide)
+doFunctionalAccess(PacketPtr pkt, bool isCpuSide)
{
if (isCpuSide)
{
missQueue->doWriteback(writebacks.front());
writebacks.pop_front();
}
- DPRINTF(Cache, "%s %x %s blk_addr: %x\n", pkt->cmdString(),
- pkt->getAddr() & (((ULL(1))<<48)-1), (blk) ? "hit" : "miss",
- pkt->getAddr() & ~((Addr)blkSize - 1));
+
+ DPRINTF(Cache, "%s %x %s\n", pkt->cmdString(), pkt->getAddr(),
+ (blk) ? "hit" : "miss");
+
if (blk) {
// Hit
hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
exitSimLoop("A cache reached the maximum miss count");
}
}
- missQueue->handleMiss(pkt, size, curTick + hitLatency);
-// return MA_CACHE_MISS;
+
+ if (pkt->flags & SATISFIED) {
+ // happens when a store conditional fails because it missed
+ // the cache completely
+ if (pkt->needsResponse())
+ respond(pkt, curTick+lat);
+ } else {
+ 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;
}
template<class TagStore, class Buffering, class Coherence>
-Packet *
+PacketPtr
Cache<TagStore,Buffering,Coherence>::getPacket()
{
assert(missQueue->havePending());
- Packet * pkt = missQueue->getPacket();
+ PacketPtr pkt = missQueue->getPacket();
if (pkt) {
if (!pkt->req->isUncacheable()) {
if (pkt->cmd == Packet::HardPFReq)
assert(!doMasterRequest() || missQueue->havePending());
assert(!pkt || pkt->time <= curTick);
+ SIGNAL_NACK_HACK = false;
return pkt;
}
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);
CacheBlk::State old_state = (blk) ? blk->status : 0;
CacheBlk::State new_state = coherence->getNewState(pkt,old_state);
if (old_state != new_state)
- DPRINTF(Cache, "Block for blk addr %x moving from "
- "state %i to %i\n",
- pkt->getAddr() & (((ULL(1))<<48)-1),
- old_state, new_state);
+ DPRINTF(Cache, "Block for blk addr %x moving from state "
+ "%i to %i\n", pkt->getAddr(), old_state, new_state);
//Set the state on the upgrade
memcpy(pkt->getPtr<uint8_t>(), blk->data, blkSize);
PacketList writebacks;
}
} else if (pkt && !pkt->req->isUncacheable()) {
pkt->flags &= ~NACKED_LINE;
+ SIGNAL_NACK_HACK = false;
pkt->flags &= ~SATISFIED;
pkt->flags &= ~SNOOP_COMMIT;
template<class TagStore, class Buffering, class Coherence>
void
-Cache<TagStore,Buffering,Coherence>::handleResponse(Packet * &pkt)
+Cache<TagStore,Buffering,Coherence>::handleResponse(PacketPtr &pkt)
{
BlkType *blk = NULL;
if (pkt->senderState) {
//Make the response a Bad address and send it
}
// MemDebug::cacheResponse(pkt);
- DPRINTF(Cache, "Handling reponse to %x, blk addr: %x\n",pkt->getAddr(),
- pkt->getAddr() & (((ULL(1))<<48)-1));
+ 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;
if (old_state != new_state)
DPRINTF(Cache, "Block for blk addr %x moving from "
"state %i to %i\n",
- pkt->getAddr() & (((ULL(1))<<48)-1),
+ pkt->getAddr(),
old_state, new_state);
blk = tags->handleFill(blk, (MSHR*)pkt->senderState,
new_state, writebacks, pkt);
}
template<class TagStore, class Buffering, class Coherence>
-Packet *
+PacketPtr
Cache<TagStore,Buffering,Coherence>::getCoherencePacket()
{
return coherence->getPacket();
template<class TagStore, class Buffering, class Coherence>
void
-Cache<TagStore,Buffering,Coherence>::sendCoherenceResult(Packet* &pkt,
+Cache<TagStore,Buffering,Coherence>::sendCoherenceResult(PacketPtr &pkt,
MSHR *cshr,
bool success)
{
template<class TagStore, class Buffering, class Coherence>
void
-Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt)
+Cache<TagStore,Buffering,Coherence>::snoop(PacketPtr &pkt)
{
if (pkt->req->isUncacheable()) {
//Can't get a hit on an uncacheable address
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");
//Append the invalidate on
missQueue->addTarget(mshr,invalidatePkt);
- DPRINTF(Cache, "Appending Invalidate to blk_addr: %x\n",
- pkt->getAddr() & (((ULL(1))<<48)-1));
+ DPRINTF(Cache, "Appending Invalidate to addr: %x\n",
+ pkt->getAddr());
return;
}
}
//We also need to check the writeback buffers and handle those
std::vector<MSHR *> writebacks;
if (missQueue->findWrites(blk_addr, writebacks)) {
- DPRINTF(Cache, "Snoop hit in writeback to blk_addr: %x\n",
- pkt->getAddr() & (((ULL(1))<<48)-1));
+ DPRINTF(Cache, "Snoop hit in writeback to addr: %x\n",
+ pkt->getAddr());
//Look through writebacks for any non-uncachable writes, use that
for (int i=0; i<writebacks.size(); i++) {
}
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",
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);
}
template<class TagStore, class Buffering, class Coherence>
void
-Cache<TagStore,Buffering,Coherence>::snoopResponse(Packet * &pkt)
+Cache<TagStore,Buffering,Coherence>::snoopResponse(PacketPtr &pkt)
{
//Need to handle the response, if NACKED
if (pkt->flags & NACKED_LINE) {
*/
template<class TagStore, class Buffering, class Coherence>
Tick
-Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update,
+Cache<TagStore,Buffering,Coherence>::probe(PacketPtr &pkt, bool update,
CachePort* otherSidePort)
{
// MemDebug::cacheProbe(pkt);
if (!pkt->req->isUncacheable()) {
- if (pkt->isInvalidate() && !pkt->isRead()
- && !pkt->isWrite()) {
+ if (pkt->isInvalidate() && !pkt->isRead() && !pkt->isWrite()) {
//Upgrade or Invalidate, satisfy it, don't forward
- DPRINTF(Cache, "%s %x ? blk_addr: %x\n", pkt->cmdString(),
- pkt->getAddr() & (((ULL(1))<<48)-1),
- pkt->getAddr() & ~((Addr)blkSize - 1));
+ DPRINTF(Cache, "%s %x ?\n", pkt->cmdString(), pkt->getAddr());
pkt->flags |= SATISFIED;
return 0;
}
}
- 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;
}
int lat;
BlkType *blk = tags->handleAccess(pkt, lat, writebacks, update);
- DPRINTF(Cache, "%s %x %s blk_addr: %x\n", pkt->cmdString(),
- pkt->getAddr() & (((ULL(1))<<48)-1), (blk) ? "hit" : "miss",
- pkt->getAddr() & ~((Addr)blkSize - 1));
+ DPRINTF(Cache, "%s %x %s\n", pkt->cmdString(),
+ pkt->getAddr(), (blk) ? "hit" : "miss");
// Need to check for outstanding misses and writes
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) {
- Packet * target = *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) {
- Packet * write = writes[i]->pkt;
+ 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;
- } else if (!blk) {
+ } else if (!blk && !(pkt->flags & SATISFIED)) {
// update the cache state and statistics
if (mshr || !writes.empty()){
- // Can't handle it, return pktuest unsatisfied.
+ // Can't handle it, return request unsatisfied.
panic("Atomic access ran into outstanding MSHR's or WB's!");
}
if (!pkt->req->isUncacheable()) {
Packet::Command temp_cmd = coherence->getBusCmd(pkt->cmd,
(blk)? blk->status : 0);
- Packet * busPkt = new Packet(pkt->req,temp_cmd, -1, blkSize);
+ PacketPtr busPkt = new Packet(pkt->req,temp_cmd, -1, blkSize);
busPkt->allocate();
busPkt->time = curTick;
- DPRINTF(Cache, "Sending a atomic %s for %x blk_addr: %x\n",
- busPkt->cmdString(),
- busPkt->getAddr() & (((ULL(1))<<48)-1),
- busPkt->getAddr() & ~((Addr)blkSize - 1));
+ DPRINTF(Cache, "Sending a atomic %s for %x\n",
+ busPkt->cmdString(), busPkt->getAddr());
lat = memSidePort->sendAtomic(busPkt);
CacheBlk::State old_state = (blk) ? blk->status : 0;
CacheBlk::State new_state =
coherence->getNewState(busPkt, old_state);
- DPRINTF(Cache,
- "Receive response:%s for blk addr %x in state %i\n",
- busPkt->cmdString(),
- busPkt->getAddr() & (((ULL(1))<<48)-1), old_state);
+ DPRINTF(Cache, "Receive response: %s for addr %x in state %i\n",
+ busPkt->cmdString(), busPkt->getAddr(), old_state);
if (old_state != new_state)
- DPRINTF(Cache, "Block for blk addr %x moving from "
- "state %i to %i\n",
- busPkt->getAddr() & (((ULL(1))<<48)-1),
- old_state, new_state);
-
- tags->handleFill(blk, busPkt,
- new_state,
- writebacks, pkt);
+ DPRINTF(Cache, "Block for blk addr %x moving from state "
+ "%i to %i\n", busPkt->getAddr(), old_state, new_state);
+
+ tags->handleFill(blk, busPkt, new_state, writebacks, pkt);
//Free the packet
delete busPkt;
// Handle writebacks if needed
while (!writebacks.empty()){
- Packet *wbPkt = writebacks.front();
+ PacketPtr wbPkt = writebacks.front();
memSidePort->sendAtomic(wbPkt);
writebacks.pop_front();
delete wbPkt;
return memSidePort->sendAtomic(pkt);
}
} else {
- // There was a cache hit.
- // Handle writebacks if needed
- while (!writebacks.empty()){
- memSidePort->sendAtomic(writebacks.front());
- writebacks.pop_front();
- }
+ if (blk) {
+ // There was a cache hit.
+ // Handle writebacks if needed
+ while (!writebacks.empty()){
+ memSidePort->sendAtomic(writebacks.front());
+ writebacks.pop_front();
+ }
- hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
+ hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
+ }
return hitLatency;
}
- fatal("Probe not handled.\n");
+
return 0;
}