noncoherent_cache.cc revision 13859
110037SARM gem5 Developers/* 210037SARM gem5 Developers * Copyright (c) 2010-2018 ARM Limited 310666SAli.Saidi@ARM.com * All rights reserved. 410037SARM gem5 Developers * 510037SARM gem5 Developers * The license below extends only to copyright in the software and shall 610037SARM gem5 Developers * not be construed as granting a license to any other intellectual 710037SARM gem5 Developers * property including but not limited to intellectual property relating 810037SARM gem5 Developers * to a hardware implementation of the functionality of the software 910037SARM gem5 Developers * licensed hereunder. You may use the software subject to the license 1010037SARM gem5 Developers * terms below provided that you ensure that this notice is replicated 1110037SARM gem5 Developers * unmodified and in its entirety in all distributions of the software, 1210037SARM gem5 Developers * modified or unmodified, in source code or in binary form. 1310037SARM gem5 Developers * 1410037SARM gem5 Developers * Copyright (c) 2002-2005 The Regents of The University of Michigan 1510037SARM gem5 Developers * Copyright (c) 2010,2015 Advanced Micro Devices, Inc. 1610037SARM gem5 Developers * All rights reserved. 1710037SARM gem5 Developers * 1810037SARM gem5 Developers * Redistribution and use in source and binary forms, with or without 1910037SARM gem5 Developers * modification, are permitted provided that the following conditions are 2010037SARM gem5 Developers * met: redistributions of source code must retain the above copyright 2110037SARM gem5 Developers * notice, this list of conditions and the following disclaimer; 2210037SARM gem5 Developers * redistributions in binary form must reproduce the above copyright 2310037SARM gem5 Developers * notice, this list of conditions and the following disclaimer in the 2410037SARM gem5 Developers * documentation and/or other materials provided with the distribution; 2510037SARM gem5 Developers * neither the name of the copyright holders nor the names of its 2610037SARM gem5 Developers * contributors may be used to endorse or promote products derived from 2710037SARM gem5 Developers * this software without specific prior written permission. 2810037SARM gem5 Developers * 2910037SARM gem5 Developers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3010037SARM gem5 Developers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3110037SARM gem5 Developers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3210037SARM gem5 Developers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3310037SARM gem5 Developers * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3410037SARM gem5 Developers * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3510037SARM gem5 Developers * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3610037SARM gem5 Developers * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3710037SARM gem5 Developers * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3810037SARM gem5 Developers * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3910037SARM gem5 Developers * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4010037SARM gem5 Developers * 4110037SARM gem5 Developers * Authors: Erik Hallnor 4210037SARM gem5 Developers * Dave Greene 4310037SARM gem5 Developers * Nathan Binkert 4410474Sandreas.hansson@arm.com * Steve Reinhardt 4510037SARM gem5 Developers * Ron Dreslinski 4610037SARM gem5 Developers * Andreas Sandberg 4710037SARM gem5 Developers * Nikos Nikoleris 4810037SARM gem5 Developers */ 4910037SARM gem5 Developers 5012234Sgabeblack@google.com/** 5110037SARM gem5 Developers * @file 5210037SARM gem5 Developers * Cache definitions. 5310037SARM gem5 Developers */ 5410037SARM gem5 Developers 5510037SARM gem5 Developers#include "mem/cache/noncoherent_cache.hh" 5610037SARM gem5 Developers 5710037SARM gem5 Developers#include <cassert> 5810037SARM gem5 Developers 5910037SARM gem5 Developers#include "base/logging.hh" 6010037SARM gem5 Developers#include "base/trace.hh" 6110037SARM gem5 Developers#include "base/types.hh" 6210037SARM gem5 Developers#include "debug/Cache.hh" 6310037SARM gem5 Developers#include "mem/cache/cache_blk.hh" 6410037SARM gem5 Developers#include "mem/cache/mshr.hh" 6510037SARM gem5 Developers#include "params/NoncoherentCache.hh" 6610037SARM gem5 Developers 6710037SARM gem5 DevelopersNoncoherentCache::NoncoherentCache(const NoncoherentCacheParams *p) 6810037SARM gem5 Developers : BaseCache(p, p->system->cacheLineSize()) 6910037SARM gem5 Developers{ 7010037SARM gem5 Developers} 7110037SARM gem5 Developers 7210037SARM gem5 Developersvoid 7310037SARM gem5 DevelopersNoncoherentCache::satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool, bool) 7412234Sgabeblack@google.com{ 7510037SARM gem5 Developers // As this a non-coherent cache located below the point of 7610037SARM gem5 Developers // coherency, we do not expect requests that are typically used to 7710037SARM gem5 Developers // keep caches coherent (e.g., InvalidateReq or UpdateReq). 7810037SARM gem5 Developers assert(pkt->isRead() || pkt->isWrite()); 7910037SARM gem5 Developers BaseCache::satisfyRequest(pkt, blk); 8010037SARM gem5 Developers} 8110037SARM gem5 Developers 8210037SARM gem5 Developersbool 8310037SARM gem5 DevelopersNoncoherentCache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, 8410037SARM gem5 Developers PacketList &writebacks) 8510037SARM gem5 Developers{ 8610037SARM gem5 Developers bool success = BaseCache::access(pkt, blk, lat, writebacks); 8710037SARM gem5 Developers 8810037SARM gem5 Developers if (pkt->isWriteback() || pkt->cmd == MemCmd::WriteClean) { 8910037SARM gem5 Developers assert(blk && blk->isValid()); 9010037SARM gem5 Developers // Writeback and WriteClean can allocate and fill even if the 9110037SARM gem5 Developers // referenced block was not present or it was invalid. If that 9210037SARM gem5 Developers // is the case, make sure that the new block is marked as 9310037SARM gem5 Developers // writable 9410037SARM gem5 Developers blk->status |= BlkWritable; 9510037SARM gem5 Developers } 9610037SARM gem5 Developers 9710037SARM gem5 Developers return success; 9810037SARM gem5 Developers} 9910037SARM gem5 Developers 10010037SARM gem5 Developersvoid 10110037SARM gem5 DevelopersNoncoherentCache::doWritebacks(PacketList& writebacks, Tick forward_time) 10212234Sgabeblack@google.com{ 10310037SARM gem5 Developers while (!writebacks.empty()) { 10410037SARM gem5 Developers PacketPtr wb_pkt = writebacks.front(); 10510037SARM gem5 Developers allocateWriteBuffer(wb_pkt, forward_time); 10610037SARM gem5 Developers writebacks.pop_front(); 10710037SARM gem5 Developers } 10810037SARM gem5 Developers} 10910037SARM gem5 Developers 11010037SARM gem5 Developersvoid 11110037SARM gem5 DevelopersNoncoherentCache::doWritebacksAtomic(PacketList& writebacks) 11210037SARM gem5 Developers{ 11310037SARM gem5 Developers while (!writebacks.empty()) { 11410037SARM gem5 Developers PacketPtr wb_pkt = writebacks.front(); 11510037SARM gem5 Developers memSidePort.sendAtomic(wb_pkt); 11610037SARM gem5 Developers writebacks.pop_front(); 11710037SARM gem5 Developers delete wb_pkt; 11810037SARM gem5 Developers } 11910037SARM gem5 Developers} 12010037SARM gem5 Developers 12110037SARM gem5 Developersvoid 12210037SARM gem5 DevelopersNoncoherentCache::handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, 12310037SARM gem5 Developers Tick forward_time, Tick request_time) 12410037SARM gem5 Developers{ 12510037SARM gem5 Developers // miss 12612234Sgabeblack@google.com Addr blk_addr = pkt->getBlockAddr(blkSize); 12710037SARM gem5 Developers MSHR *mshr = mshrQueue.findMatch(blk_addr, pkt->isSecure(), false); 12810037SARM gem5 Developers 12910037SARM gem5 Developers // We can always write to a non coherent cache if the block is 13010037SARM gem5 Developers // present and therefore if we have reached this point then the 13110037SARM gem5 Developers // block should not be in the cache. 13210037SARM gem5 Developers assert(mshr || !blk || !blk->isValid()); 13310037SARM gem5 Developers 13410037SARM gem5 Developers BaseCache::handleTimingReqMiss(pkt, mshr, blk, forward_time, request_time); 13510037SARM gem5 Developers} 13610037SARM gem5 Developers 13710037SARM gem5 Developersvoid 13810037SARM gem5 DevelopersNoncoherentCache::recvTimingReq(PacketPtr pkt) 13910037SARM gem5 Developers{ 14010037SARM gem5 Developers panic_if(pkt->cacheResponding(), "Should not see packets where cache " 14110037SARM gem5 Developers "is responding"); 14210037SARM gem5 Developers 14310037SARM gem5 Developers panic_if(!(pkt->isRead() || pkt->isWrite()), 14410037SARM gem5 Developers "Should only see read and writes at non-coherent cache\n"); 14510037SARM gem5 Developers 14610037SARM gem5 Developers BaseCache::recvTimingReq(pkt); 14710037SARM gem5 Developers} 14810037SARM gem5 Developers 14910037SARM gem5 DevelopersPacketPtr 15010037SARM gem5 DevelopersNoncoherentCache::createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk, 15110037SARM gem5 Developers bool needs_writable, 15210037SARM gem5 Developers bool is_whole_line_write) const 15310037SARM gem5 Developers{ 15410037SARM gem5 Developers // We also fill for writebacks from the coherent caches above us, 15510037SARM gem5 Developers // and they do not need responses 15610037SARM gem5 Developers assert(cpu_pkt->needsResponse()); 15710037SARM gem5 Developers 15810037SARM gem5 Developers // A miss can happen only due to missing block 15912234Sgabeblack@google.com assert(!blk || !blk->isValid()); 16010037SARM gem5 Developers 16110037SARM gem5 Developers PacketPtr pkt = new Packet(cpu_pkt->req, MemCmd::ReadReq, blkSize); 16210037SARM gem5 Developers 16310037SARM gem5 Developers // the packet should be block aligned 16410037SARM gem5 Developers assert(pkt->getAddr() == pkt->getBlockAddr(blkSize)); 16510037SARM gem5 Developers 16610037SARM gem5 Developers pkt->allocate(); 16710037SARM gem5 Developers DPRINTF(Cache, "%s created %s from %s\n", __func__, pkt->print(), 16810037SARM gem5 Developers cpu_pkt->print()); 16910037SARM gem5 Developers return pkt; 17010037SARM gem5 Developers} 17110037SARM gem5 Developers 17210037SARM gem5 Developers 17310037SARM gem5 DevelopersCycles 17410037SARM gem5 DevelopersNoncoherentCache::handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk, 17510037SARM gem5 Developers PacketList &writebacks) 17610037SARM gem5 Developers{ 17710037SARM gem5 Developers PacketPtr bus_pkt = createMissPacket(pkt, blk, true, 17810037SARM gem5 Developers pkt->isWholeLineWrite(blkSize)); 17910037SARM gem5 Developers DPRINTF(Cache, "Sending an atomic %s\n", bus_pkt->print()); 18010037SARM gem5 Developers 18110037SARM gem5 Developers Cycles latency = ticksToCycles(memSidePort.sendAtomic(bus_pkt)); 18210037SARM gem5 Developers 18312234Sgabeblack@google.com assert(bus_pkt->isResponse()); 18410037SARM gem5 Developers // At the moment the only supported downstream requests we issue 18510037SARM gem5 Developers // are ReadReq and therefore here we should only see the 18610037SARM gem5 Developers // corresponding responses 18710037SARM gem5 Developers assert(bus_pkt->isRead()); 18810037SARM gem5 Developers assert(pkt->cmd != MemCmd::UpgradeResp); 18910037SARM gem5 Developers assert(!bus_pkt->isInvalidate()); 19010037SARM gem5 Developers assert(!bus_pkt->hasSharers()); 19110037SARM gem5 Developers 19210037SARM gem5 Developers // We are now dealing with the response handling 19310037SARM gem5 Developers DPRINTF(Cache, "Receive response: %s\n", bus_pkt->print()); 19411303Ssteve.reinhardt@amd.com 19510037SARM gem5 Developers if (!bus_pkt->isError()) { 19610037SARM gem5 Developers // Any reponse that does not have an error should be filling, 19710037SARM gem5 Developers // afterall it is a read response 19810037SARM gem5 Developers DPRINTF(Cache, "Block for addr %#llx being updated in Cache\n", 19910037SARM gem5 Developers bus_pkt->getAddr()); 20010037SARM gem5 Developers blk = handleFill(bus_pkt, blk, writebacks, allocOnFill(bus_pkt->cmd)); 20110037SARM gem5 Developers assert(blk); 20212234Sgabeblack@google.com } 20310037SARM gem5 Developers satisfyRequest(pkt, blk); 20410037SARM gem5 Developers 20510037SARM gem5 Developers maintainClusivity(true, blk); 20610037SARM gem5 Developers 20710037SARM gem5 Developers // Use the separate bus_pkt to generate response to pkt and 20810037SARM gem5 Developers // then delete it. 20910037SARM gem5 Developers if (!pkt->isWriteback() && pkt->cmd != MemCmd::WriteClean) { 21010037SARM gem5 Developers assert(pkt->needsResponse()); 21110037SARM gem5 Developers pkt->makeAtomicResponse(); 21210037SARM gem5 Developers if (bus_pkt->isError()) { 21310037SARM gem5 Developers pkt->copyError(bus_pkt); 21410037SARM gem5 Developers } 21510037SARM gem5 Developers } 21610037SARM gem5 Developers 21710037SARM gem5 Developers delete bus_pkt; 21810037SARM gem5 Developers 21910037SARM gem5 Developers return latency; 22010037SARM gem5 Developers} 22110037SARM gem5 Developers 22210037SARM gem5 DevelopersTick 22310037SARM gem5 DevelopersNoncoherentCache::recvAtomic(PacketPtr pkt) 22410037SARM gem5 Developers{ 22510037SARM gem5 Developers panic_if(pkt->cacheResponding(), "Should not see packets where cache " 22612234Sgabeblack@google.com "is responding"); 22710037SARM gem5 Developers 22810037SARM gem5 Developers panic_if(!(pkt->isRead() || pkt->isWrite()), 22910037SARM gem5 Developers "Should only see read and writes at non-coherent cache\n"); 23010037SARM gem5 Developers 23110037SARM gem5 Developers return BaseCache::recvAtomic(pkt); 23210037SARM gem5 Developers} 23310037SARM gem5 Developers 23412234Sgabeblack@google.com 23510037SARM gem5 Developersvoid 23610037SARM gem5 DevelopersNoncoherentCache::functionalAccess(PacketPtr pkt, bool from_cpu_side) 23710037SARM gem5 Developers{ 23810037SARM gem5 Developers panic_if(!from_cpu_side, "Non-coherent cache received functional snoop" 23910037SARM gem5 Developers " request\n"); 24010037SARM gem5 Developers 24110037SARM gem5 Developers BaseCache::functionalAccess(pkt, from_cpu_side); 24210037SARM gem5 Developers} 24310037SARM gem5 Developers 24410037SARM gem5 Developersvoid 24510037SARM gem5 DevelopersNoncoherentCache::serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt, 24610037SARM gem5 Developers CacheBlk *blk) 24710037SARM gem5 Developers{ 24810037SARM gem5 Developers // First offset for critical word first calculations 24910037SARM gem5 Developers const int initial_offset = mshr->getTarget()->pkt->getOffset(blkSize); 25010037SARM gem5 Developers 25110037SARM gem5 Developers MSHR::TargetList targets = mshr->extractServiceableTargets(pkt); 25210037SARM gem5 Developers for (auto &target: targets) { 25310037SARM gem5 Developers Packet *tgt_pkt = target.pkt; 25410037SARM gem5 Developers 25510037SARM gem5 Developers switch (target.source) { 25610037SARM gem5 Developers case MSHR::Target::FromCPU: 25710037SARM gem5 Developers // handle deferred requests comming from a cache or core 25810037SARM gem5 Developers // above 25910037SARM gem5 Developers 26010037SARM gem5 Developers Tick completion_time; 26112236Sgabeblack@google.com // Here we charge on completion_time the delay of the xbar if the 26212236Sgabeblack@google.com // packet comes from it, charged on headerDelay. 26312236Sgabeblack@google.com completion_time = pkt->headerDelay; 26410037SARM gem5 Developers 26510037SARM gem5 Developers satisfyRequest(tgt_pkt, blk); 26610037SARM gem5 Developers 26710037SARM gem5 Developers // How many bytes past the first request is this one 26810037SARM gem5 Developers int transfer_offset; 26910037SARM gem5 Developers transfer_offset = tgt_pkt->getOffset(blkSize) - initial_offset; 27010037SARM gem5 Developers if (transfer_offset < 0) { 27110037SARM gem5 Developers transfer_offset += blkSize; 27210037SARM gem5 Developers } 27310037SARM gem5 Developers // If not critical word (offset) return payloadDelay. 27410037SARM gem5 Developers // responseLatency is the latency of the return path 27510037SARM gem5 Developers // from lower level caches/memory to an upper level cache or 27610037SARM gem5 Developers // the core. 27710037SARM gem5 Developers completion_time += clockEdge(responseLatency) + 27810037SARM gem5 Developers (transfer_offset ? pkt->payloadDelay : 0); 27910037SARM gem5 Developers 28010037SARM gem5 Developers assert(tgt_pkt->req->masterId() < system->maxMasters()); 28110037SARM gem5 Developers missLatency[tgt_pkt->cmdToIndex()][tgt_pkt->req->masterId()] += 28210037SARM gem5 Developers completion_time - target.recvTime; 28312234Sgabeblack@google.com 28410037SARM gem5 Developers tgt_pkt->makeTimingResponse(); 28510037SARM gem5 Developers if (pkt->isError()) 28610037SARM gem5 Developers tgt_pkt->copyError(pkt); 28710037SARM gem5 Developers 28810037SARM gem5 Developers // Reset the bus additional time as it is now accounted for 28910037SARM gem5 Developers tgt_pkt->headerDelay = tgt_pkt->payloadDelay = 0; 29010037SARM gem5 Developers cpuSidePort.schedTimingResp(tgt_pkt, completion_time); 29110037SARM gem5 Developers break; 29210037SARM gem5 Developers 29310037SARM gem5 Developers case MSHR::Target::FromPrefetcher: 29410037SARM gem5 Developers // handle deferred requests comming from a prefetcher 29510037SARM gem5 Developers // attached to this cache 29610037SARM gem5 Developers assert(tgt_pkt->cmd == MemCmd::HardPFReq); 29710037SARM gem5 Developers 29810037SARM gem5 Developers if (blk) 29910037SARM gem5 Developers blk->status |= BlkHWPrefetched; 30010037SARM gem5 Developers 30110037SARM gem5 Developers // We have filled the block and the prefetcher does not 30210037SARM gem5 Developers // require responses. 30310037SARM gem5 Developers delete tgt_pkt; 30410037SARM gem5 Developers break; 30510037SARM gem5 Developers 30610037SARM gem5 Developers default: 30710037SARM gem5 Developers // we should never see FromSnoop Targets as this is a 30810037SARM gem5 Developers // non-coherent cache 30910037SARM gem5 Developers panic("Illegal target->source enum %d\n", target.source); 31010037SARM gem5 Developers } 31112234Sgabeblack@google.com } 31210037SARM gem5 Developers 31310037SARM gem5 Developers // Reponses are filling and bring in writable blocks, therefore 31410037SARM gem5 Developers // there should be no deferred targets and all the non-deferred 31510037SARM gem5 Developers // targets are now serviced. 31610037SARM gem5 Developers assert(mshr->getNumTargets() == 0); 31710037SARM gem5 Developers} 31810037SARM gem5 Developers 31910037SARM gem5 Developersvoid 32010037SARM gem5 DevelopersNoncoherentCache::recvTimingResp(PacketPtr pkt) 32110037SARM gem5 Developers{ 32210037SARM gem5 Developers assert(pkt->isResponse()); 32310037SARM gem5 Developers // At the moment the only supported downstream requests we issue 32410037SARM gem5 Developers // are ReadReq and therefore here we should only see the 32510037SARM gem5 Developers // corresponding responses 32610037SARM gem5 Developers assert(pkt->isRead()); 32710037SARM gem5 Developers assert(pkt->cmd != MemCmd::UpgradeResp); 32810037SARM gem5 Developers assert(!pkt->isInvalidate()); 32910037SARM gem5 Developers // This cache is non-coherent and any memories below are 33010037SARM gem5 Developers // non-coherent too (non-coherent caches or the main memory), 33110037SARM gem5 Developers // therefore the fetched block can be marked as writable. 33210037SARM gem5 Developers assert(!pkt->hasSharers()); 33310037SARM gem5 Developers 33410037SARM gem5 Developers BaseCache::recvTimingResp(pkt); 33510037SARM gem5 Developers} 33610037SARM gem5 Developers 33710037SARM gem5 DevelopersPacketPtr 33810037SARM gem5 DevelopersNoncoherentCache::evictBlock(CacheBlk *blk) 33910037SARM gem5 Developers{ 34010037SARM gem5 Developers // A dirty block is always written back. 34110037SARM gem5 Developers 34210037SARM gem5 Developers // A clean block can we written back, if we turned on writebacks 34312236Sgabeblack@google.com // for clean blocks. This could be useful if there is a cache 34412236Sgabeblack@google.com // below and we want to make sure the block is cached but if the 34512236Sgabeblack@google.com // memory below is the main memory WritebackCleans are 34610037SARM gem5 Developers // unnecessary. 34710037SARM gem5 Developers 34810037SARM gem5 Developers // If we clean writebacks are not enabled, we do not take any 34910037SARM gem5 Developers // further action for evictions of clean blocks (i.e., CleanEvicts 35010037SARM gem5 Developers // are unnecessary). 35110037SARM gem5 Developers PacketPtr pkt = (blk->isDirty() || writebackClean) ? 35210037SARM gem5 Developers writebackBlk(blk) : nullptr; 35310037SARM gem5 Developers 35410037SARM gem5 Developers invalidateBlock(blk); 35510037SARM gem5 Developers 35610037SARM gem5 Developers return pkt; 35710037SARM gem5 Developers} 35810037SARM gem5 Developers 35910037SARM gem5 DevelopersNoncoherentCache* 36010037SARM gem5 DevelopersNoncoherentCacheParams::create() 36110037SARM gem5 Developers{ 36210037SARM gem5 Developers assert(tags); 36310037SARM gem5 Developers assert(replacement_policy); 36410037SARM gem5 Developers 36512236Sgabeblack@google.com return new NoncoherentCache(this); 36612236Sgabeblack@google.com} 36712236Sgabeblack@google.com