72a73
> writebackClean(p->writeback_clean),
320c321
< if (old_blk->isDirty())
---
> if (old_blk->isDirty() || writebackClean)
346c347
< if (pkt->evictingBlock()) {
---
> if (pkt->isEviction()) {
359,371c360,383
< PacketPtr wbPkt = outgoing[0]->getTarget()->pkt;
< assert(pkt->cmd == MemCmd::CleanEvict &&
< wbPkt->cmd == MemCmd::Writeback);
< // As the CleanEvict is coming from above, it would have snooped
< // into other peer caches of the same level while traversing the
< // crossbar. If a copy of the block had been found, the CleanEvict
< // would have been deleted in the crossbar. Now that the
< // CleanEvict is here we can be sure none of the other upper level
< // caches connected to this cache have the block, so we can clear
< // the BLOCK_CACHED flag in the Writeback if set and discard the
< // CleanEvict by returning true.
< wbPkt->clearBlockCached();
< return true;
---
> MSHR *wb_entry = outgoing[0];
> assert(wb_entry->getNumTargets() == 1);
> PacketPtr wbPkt = wb_entry->getTarget()->pkt;
> assert(wbPkt->isWriteback());
>
> if (pkt->isCleanEviction()) {
> // The CleanEvict and WritebackClean snoops into other
> // peer caches of the same level while traversing the
> // crossbar. If a copy of the block is found, the
> // packet is deleted in the crossbar. Hence, none of
> // the other upper level caches connected to this
> // cache have the block, so we can clear the
> // BLOCK_CACHED flag in the Writeback if set and
> // discard the CleanEvict by returning true.
> wbPkt->clearBlockCached();
> return true;
> } else {
> assert(pkt->cmd == MemCmd::WritebackDirty);
> // Dirty writeback from above trumps our clean
> // writeback... discard here
> // Note: markInService will remove entry from writeback buffer.
> markInService(wb_entry, false);
> delete wbPkt;
> }
377c389
< if (pkt->cmd == MemCmd::Writeback) {
---
> if (pkt->isWriteback()) {
378a391,402
>
> // we could get a clean writeback while we are having
> // outstanding accesses to a block, do the simple thing for
> // now and drop the clean writeback so that we do not upset
> // any ordering/decisions about ownership already taken
> if (pkt->cmd == MemCmd::WritebackClean &&
> mshrQueue.findMatch(pkt->getAddr(), pkt->isSecure())) {
> DPRINTF(Cache, "Clean writeback %#llx to block with MSHR, "
> "dropping\n", pkt->getAddr());
> return true;
> }
>
394c418,422
< blk->status |= BlkDirty;
---
> // only mark the block dirty if we got a writeback command,
> // and leave it as is for a clean writeback
> if (pkt->cmd == MemCmd::WritebackDirty) {
> blk->status |= BlkDirty;
> }
465a494,498
> } else if (wbPkt->cmd == MemCmd::WritebackClean) {
> // clean writeback, do not send since the block is
> // still cached above
> assert(writebackClean);
> delete wbPkt;
466a500
> assert(wbPkt->cmd == MemCmd::WritebackDirty);
493c527
< if (wbPkt->cmd == MemCmd::Writeback) {
---
> if (wbPkt->cmd == MemCmd::WritebackDirty) {
696a731,734
> DPRINTF(Cache, "%s satisfied %s addr %#llx, no response needed\n",
> __func__, pkt->cmdString(), pkt->getAddr(),
> pkt->getSize());
>
768,770c806,808
< assert(pkt->cmd != MemCmd::Writeback);
< // CleanEvicts corresponding to blocks which have outstanding
< // requests in MSHRs can be deleted here.
---
> assert(!pkt->isWriteback());
> // CleanEvicts corresponding to blocks which have
> // outstanding requests in MSHRs are simply sunk here
823c861
< if (pkt->evictingBlock() ||
---
> if (pkt->isEviction() ||
891c929
< cpu_pkt->evictingBlock())) {
---
> cpu_pkt->isEviction())) {
1111,1112c1149,1150
< tempBlockWriteback = blk->isDirty() ? writebackBlk(blk) :
< cleanEvictBlk(blk);
---
> tempBlockWriteback = (blk->isDirty() || writebackClean) ?
> writebackBlk(blk) : cleanEvictBlk(blk);
1461c1499
< if (blk->isDirty()) {
---
> if (blk->isDirty() || writebackClean) {
1487,1488c1525,1527
< chatty_assert(!isReadOnly, "Writeback from read-only cache");
< assert(blk && blk->isValid() && blk->isDirty());
---
> chatty_assert(!isReadOnly || writebackClean,
> "Writeback from read-only cache");
> assert(blk && blk->isValid() && (blk->isDirty() || writebackClean));
1492,1494c1531,1532
< Request *writebackReq =
< new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0,
< Request::wbMasterId);
---
> Request *req = new Request(tags->regenerateBlkAddr(blk->tag, blk->set),
> blkSize, 0, Request::wbMasterId);
1496c1534
< writebackReq->setFlags(Request::SECURE);
---
> req->setFlags(Request::SECURE);
1498c1536
< writebackReq->taskId(blk->task_id);
---
> req->taskId(blk->task_id);
1502c1540,1546
< PacketPtr writeback = new Packet(writebackReq, MemCmd::Writeback);
---
> PacketPtr pkt =
> new Packet(req, blk->isDirty() ?
> MemCmd::WritebackDirty : MemCmd::WritebackClean);
>
> DPRINTF(Cache, "Create Writeback %#llx writable: %d, dirty: %d\n",
> pkt->getAddr(), blk->isWritable(), blk->isDirty());
>
1509c1553
< writeback->assertShared();
---
> pkt->assertShared();
1512,1514c1556
< writeback->allocate();
< std::memcpy(writeback->getPtr<uint8_t>(), blk->data, blkSize);
<
---
> // make sure the block is not marked dirty
1516c1558,1562
< return writeback;
---
>
> pkt->allocate();
> std::memcpy(pkt->getPtr<uint8_t>(), blk->data, blkSize);
>
> return pkt;
1521a1568
> assert(!writebackClean);
1631c1678
< if (blk->isDirty()) {
---
> if (blk->isDirty() || writebackClean) {
2054c2101
< assert(wb_pkt->evictingBlock());
---
> assert(wb_pkt->isEviction());
2056c2103
< if (pkt->evictingBlock()) {
---
> if (pkt->isEviction()) {
2067c2114
< if (wb_pkt->cmd == MemCmd::Writeback) {
---
> if (wb_pkt->cmd == MemCmd::WritebackDirty) {
2085c2132,2135
< assert(wb_pkt->cmd == MemCmd::CleanEvict);
---
> // on hitting a clean writeback we play it safe and do not
> // provide a response, the block may be dirty somewhere
> // else
> assert(wb_pkt->isCleanEviction());
2087c2137
< // corresponding CleanEvict message reaches the crossbar
---
> // corresponding message reaches the crossbar
2089,2093c2139,2143
< // message we must set assertShared (just like when it
< // encounters a Writeback) to avoid the snoop filter
< // prematurely clearing the holder bit in the crossbar
< // below
< if (!pkt->needsExclusive())
---
> // or WritebackClean message we must set assertShared
> // (just like when it encounters a Writeback) to avoid the
> // snoop filter prematurely clearing the holder bit in the
> // crossbar below
> if (!pkt->needsExclusive()) {
2095c2145,2149
< else
---
> // the writeback is no longer passing exclusivity (the
> // receiving cache should consider the block owned
> // rather than modified)
> wb_pkt->assertShared();
> } else {
2096a2151
> }
2246c2301
< assert(pkt->evictingBlock());
---
> assert(pkt->isEviction());
2315c2370
< if (tgt_pkt->cmd != MemCmd::Writeback) {
---
> if (!tgt_pkt->isWriteback()) {