simple_cache.cc revision 14252
16242Sgblack@eecs.umich.edu/* 212529Sgiacomo.travaglini@arm.com * Copyright (c) 2017 Jason Lowe-Power 37093Sgblack@eecs.umich.edu * All rights reserved. 47093Sgblack@eecs.umich.edu * 57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146242Sgblack@eecs.umich.edu * this software without specific prior written permission. 156242Sgblack@eecs.umich.edu * 166242Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176242Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186242Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196242Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206242Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216242Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226242Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236242Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246242Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256242Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266242Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276242Sgblack@eecs.umich.edu * 286242Sgblack@eecs.umich.edu * Authors: Jason Lowe-Power 296242Sgblack@eecs.umich.edu */ 306242Sgblack@eecs.umich.edu 316242Sgblack@eecs.umich.edu#include "learning_gem5/part2/simple_cache.hh" 326242Sgblack@eecs.umich.edu 336242Sgblack@eecs.umich.edu#include "base/random.hh" 346242Sgblack@eecs.umich.edu#include "debug/SimpleCache.hh" 356242Sgblack@eecs.umich.edu#include "sim/system.hh" 366242Sgblack@eecs.umich.edu 376242Sgblack@eecs.umich.eduSimpleCache::SimpleCache(SimpleCacheParams *params) : 386242Sgblack@eecs.umich.edu ClockedObject(params), 396242Sgblack@eecs.umich.edu latency(params->latency), 406242Sgblack@eecs.umich.edu blockSize(params->system->cacheLineSize()), 4110037SARM gem5 Developers capacity(params->size / blockSize), 426242Sgblack@eecs.umich.edu memPort(params->name + ".mem_side", this), 436242Sgblack@eecs.umich.edu blocked(false), originalPacket(nullptr), waitingPortId(-1) 446242Sgblack@eecs.umich.edu{ 456242Sgblack@eecs.umich.edu // Since the CPU side ports are a vector of ports, create an instance of 4610037SARM gem5 Developers // the CPUSidePort for each connection. This member of params is 4711939Snikos.nikoleris@arm.com // automatically created depending on the name of the vector port and 4810037SARM gem5 Developers // holds the number of connections to this port name 496242Sgblack@eecs.umich.edu for (int i = 0; i < params->port_cpu_side_connection_count; ++i) { 509256SAndreas.Sandberg@arm.com cpuPorts.emplace_back(name() + csprintf(".cpu_side[%d]", i), i, this); 516242Sgblack@eecs.umich.edu } 5210037SARM gem5 Developers} 5310037SARM gem5 Developers 5410037SARM gem5 DevelopersPort & 556242Sgblack@eecs.umich.eduSimpleCache::getPort(const std::string &if_name, PortID idx) 566242Sgblack@eecs.umich.edu{ 576242Sgblack@eecs.umich.edu // This is the name from the Python SimObject declaration in SimpleCache.py 5810037SARM gem5 Developers if (if_name == "mem_side") { 5910037SARM gem5 Developers panic_if(idx != InvalidPortID, 6010037SARM gem5 Developers "Mem side of simple cache not a vector port"); 6110037SARM gem5 Developers return memPort; 6210037SARM gem5 Developers } else if (if_name == "cpu_side" && idx < cpuPorts.size()) { 6310037SARM gem5 Developers // We should have already created all of the ports in the constructor 6410037SARM gem5 Developers return cpuPorts[idx]; 6510037SARM gem5 Developers } else { 6610037SARM gem5 Developers // pass it along to our super class 6710037SARM gem5 Developers return ClockedObject::getPort(if_name, idx); 6810037SARM gem5 Developers } 6910037SARM gem5 Developers} 7010037SARM gem5 Developers 7110037SARM gem5 Developersvoid 7210037SARM gem5 DevelopersSimpleCache::CPUSidePort::sendPacket(PacketPtr pkt) 737259Sgblack@eecs.umich.edu{ 7410037SARM gem5 Developers // Note: This flow control is very simple since the cache is blocking. 7510037SARM gem5 Developers 7610037SARM gem5 Developers panic_if(blockedPacket != nullptr, "Should never try to send if blocked!"); 7710037SARM gem5 Developers 7810037SARM gem5 Developers // If we can't send the packet across the port, store it for later. 7910037SARM gem5 Developers DPRINTF(SimpleCache, "Sending %s to CPU\n", pkt->print()); 8010037SARM gem5 Developers if (!sendTimingResp(pkt)) { 8110037SARM gem5 Developers DPRINTF(SimpleCache, "failed!\n"); 8210037SARM gem5 Developers blockedPacket = pkt; 8310037SARM gem5 Developers } 8410037SARM gem5 Developers} 8510037SARM gem5 Developers 8610037SARM gem5 DevelopersAddrRangeList 8710037SARM gem5 DevelopersSimpleCache::CPUSidePort::getAddrRanges() const 8810037SARM gem5 Developers{ 8910037SARM gem5 Developers return owner->getAddrRanges(); 908868SMatt.Horsnell@arm.com} 9110037SARM gem5 Developers 9210037SARM gem5 Developersvoid 9310037SARM gem5 DevelopersSimpleCache::CPUSidePort::trySendRetry() 9410037SARM gem5 Developers{ 9510037SARM gem5 Developers if (needRetry && blockedPacket == nullptr) { 9610037SARM gem5 Developers // Only send a retry if the port is now completely free 9710037SARM gem5 Developers needRetry = false; 9810037SARM gem5 Developers DPRINTF(SimpleCache, "Sending retry req.\n"); 9910037SARM gem5 Developers sendRetryReq(); 10010037SARM gem5 Developers } 10110037SARM gem5 Developers} 10210037SARM gem5 Developers 10310037SARM gem5 Developersvoid 10410037SARM gem5 DevelopersSimpleCache::CPUSidePort::recvFunctional(PacketPtr pkt) 10510037SARM gem5 Developers{ 10610037SARM gem5 Developers // Just forward to the cache. 10710037SARM gem5 Developers return owner->handleFunctional(pkt); 10810037SARM gem5 Developers} 10910037SARM gem5 Developers 11010037SARM gem5 Developersbool 11110037SARM gem5 DevelopersSimpleCache::CPUSidePort::recvTimingReq(PacketPtr pkt) 11210037SARM gem5 Developers{ 11310037SARM gem5 Developers DPRINTF(SimpleCache, "Got request %s\n", pkt->print()); 11410037SARM gem5 Developers 11510037SARM gem5 Developers if (blockedPacket || needRetry) { 11610037SARM gem5 Developers // The cache may not be able to send a reply if this is blocked 11710037SARM gem5 Developers DPRINTF(SimpleCache, "Request blocked\n"); 11810037SARM gem5 Developers needRetry = true; 11910037SARM gem5 Developers return false; 12010037SARM gem5 Developers } 12110037SARM gem5 Developers // Just forward to the cache. 12210037SARM gem5 Developers if (!owner->handleRequest(pkt, id)) { 12310037SARM gem5 Developers DPRINTF(SimpleCache, "Request failed\n"); 12410037SARM gem5 Developers // stalling 12510037SARM gem5 Developers needRetry = true; 12610037SARM gem5 Developers return false; 12710037SARM gem5 Developers } else { 12810037SARM gem5 Developers DPRINTF(SimpleCache, "Request succeeded\n"); 12910037SARM gem5 Developers return true; 13010037SARM gem5 Developers } 13110037SARM gem5 Developers} 13210037SARM gem5 Developers 13310037SARM gem5 Developersvoid 13410037SARM gem5 DevelopersSimpleCache::CPUSidePort::recvRespRetry() 13510037SARM gem5 Developers{ 13610037SARM gem5 Developers // We should have a blocked packet if this function is called. 13711768SCurtis.Dunham@arm.com assert(blockedPacket != nullptr); 13810037SARM gem5 Developers 13911768SCurtis.Dunham@arm.com // Grab the blocked packet. 14010037SARM gem5 Developers PacketPtr pkt = blockedPacket; 14110037SARM gem5 Developers blockedPacket = nullptr; 1427351Sgblack@eecs.umich.edu 14310037SARM gem5 Developers DPRINTF(SimpleCache, "Retrying response pkt %s\n", pkt->print()); 14410037SARM gem5 Developers // Try to resend it. It's possible that it fails again. 14510037SARM gem5 Developers sendPacket(pkt); 14610037SARM gem5 Developers 14710037SARM gem5 Developers // We may now be able to accept new packets 14810037SARM gem5 Developers trySendRetry(); 14910037SARM gem5 Developers} 15010037SARM gem5 Developers 15110037SARM gem5 Developersvoid 15210037SARM gem5 DevelopersSimpleCache::MemSidePort::sendPacket(PacketPtr pkt) 15310037SARM gem5 Developers{ 15410037SARM gem5 Developers // Note: This flow control is very simple since the cache is blocking. 15510037SARM gem5 Developers 15610037SARM gem5 Developers panic_if(blockedPacket != nullptr, "Should never try to send if blocked!"); 15710037SARM gem5 Developers 15810037SARM gem5 Developers // If we can't send the packet across the port, store it for later. 15910037SARM gem5 Developers if (!sendTimingReq(pkt)) { 16010037SARM gem5 Developers blockedPacket = pkt; 16110037SARM gem5 Developers } 16210037SARM gem5 Developers} 16310037SARM gem5 Developers 16410037SARM gem5 Developersbool 16510037SARM gem5 DevelopersSimpleCache::MemSidePort::recvTimingResp(PacketPtr pkt) 16610037SARM gem5 Developers{ 16710037SARM gem5 Developers // Just forward to the cache. 16810037SARM gem5 Developers return owner->handleResponse(pkt); 16910037SARM gem5 Developers} 17010037SARM gem5 Developers 17110037SARM gem5 Developersvoid 17210037SARM gem5 DevelopersSimpleCache::MemSidePort::recvReqRetry() 17310037SARM gem5 Developers{ 17410037SARM gem5 Developers // We should have a blocked packet if this function is called. 17510037SARM gem5 Developers assert(blockedPacket != nullptr); 17610037SARM gem5 Developers 17710037SARM gem5 Developers // Grab the blocked packet. 17810037SARM gem5 Developers PacketPtr pkt = blockedPacket; 17910037SARM gem5 Developers blockedPacket = nullptr; 18010037SARM gem5 Developers 18110037SARM gem5 Developers // Try to resend it. It's possible that it fails again. 18210037SARM gem5 Developers sendPacket(pkt); 18310037SARM gem5 Developers} 18410037SARM gem5 Developers 18510037SARM gem5 Developersvoid 18610037SARM gem5 DevelopersSimpleCache::MemSidePort::recvRangeChange() 18710037SARM gem5 Developers{ 18810037SARM gem5 Developers owner->sendRangeChange(); 18910037SARM gem5 Developers} 19010037SARM gem5 Developers 19110037SARM gem5 Developersbool 19210037SARM gem5 DevelopersSimpleCache::handleRequest(PacketPtr pkt, int port_id) 19310037SARM gem5 Developers{ 19410037SARM gem5 Developers if (blocked) { 19510037SARM gem5 Developers // There is currently an outstanding request so we can't respond. Stall 19610037SARM gem5 Developers return false; 19710037SARM gem5 Developers } 19810037SARM gem5 Developers 19910037SARM gem5 Developers DPRINTF(SimpleCache, "Got request for addr %#x\n", pkt->getAddr()); 20010037SARM gem5 Developers 20110037SARM gem5 Developers // This cache is now blocked waiting for the response to this packet. 20210037SARM gem5 Developers blocked = true; 20310037SARM gem5 Developers 20410037SARM gem5 Developers // Store the port for when we get the response 20510037SARM gem5 Developers assert(waitingPortId == -1); 20610037SARM gem5 Developers waitingPortId = port_id; 20710037SARM gem5 Developers 20810037SARM gem5 Developers // Schedule an event after cache access latency to actually access 20910037SARM gem5 Developers schedule(new EventFunctionWrapper([this, pkt]{ accessTiming(pkt); }, 21010037SARM gem5 Developers name() + ".accessEvent", true), 21110037SARM gem5 Developers clockEdge(latency)); 21210037SARM gem5 Developers 21310037SARM gem5 Developers return true; 21410037SARM gem5 Developers} 21510037SARM gem5 Developers 21610037SARM gem5 Developersbool 21710037SARM gem5 DevelopersSimpleCache::handleResponse(PacketPtr pkt) 21810037SARM gem5 Developers{ 21910037SARM gem5 Developers assert(blocked); 22010037SARM gem5 Developers DPRINTF(SimpleCache, "Got response for addr %#x\n", pkt->getAddr()); 22110037SARM gem5 Developers 22210037SARM gem5 Developers // For now assume that inserts are off of the critical path and don't count 22310037SARM gem5 Developers // for any added latency. 22410037SARM gem5 Developers insert(pkt); 22510037SARM gem5 Developers 22610037SARM gem5 Developers missLatency.sample(curTick() - missTime); 22710037SARM gem5 Developers 22810037SARM gem5 Developers // If we had to upgrade the request packet to a full cache line, now we 22910037SARM gem5 Developers // can use that packet to construct the response. 23010037SARM gem5 Developers if (originalPacket != nullptr) { 23110037SARM gem5 Developers DPRINTF(SimpleCache, "Copying data from new packet to old\n"); 23210037SARM gem5 Developers // We had to upgrade a previous packet. We can functionally deal with 23310037SARM gem5 Developers // the cache access now. It better be a hit. 23410037SARM gem5 Developers bool hit M5_VAR_USED = accessFunctional(originalPacket); 23510037SARM gem5 Developers panic_if(!hit, "Should always hit after inserting"); 23610037SARM gem5 Developers originalPacket->makeResponse(); 23710037SARM gem5 Developers delete pkt; // We may need to delay this, I'm not sure. 23810037SARM gem5 Developers pkt = originalPacket; 23910037SARM gem5 Developers originalPacket = nullptr; 24010037SARM gem5 Developers } // else, pkt contains the data it needs 24110037SARM gem5 Developers 24210037SARM gem5 Developers sendResponse(pkt); 24310037SARM gem5 Developers 24410037SARM gem5 Developers return true; 24510037SARM gem5 Developers} 24610037SARM gem5 Developers 24710037SARM gem5 Developersvoid SimpleCache::sendResponse(PacketPtr pkt) 24810037SARM gem5 Developers{ 24910037SARM gem5 Developers assert(blocked); 25010037SARM gem5 Developers DPRINTF(SimpleCache, "Sending resp for addr %#x\n", pkt->getAddr()); 25110037SARM gem5 Developers 25210037SARM gem5 Developers int port = waitingPortId; 25310037SARM gem5 Developers 25410037SARM gem5 Developers // The packet is now done. We're about to put it in the port, no need for 25510037SARM gem5 Developers // this object to continue to stall. 25610037SARM gem5 Developers // We need to free the resource before sending the packet in case the CPU 25710037SARM gem5 Developers // tries to send another request immediately (e.g., in the same callchain). 25810037SARM gem5 Developers blocked = false; 25910037SARM gem5 Developers waitingPortId = -1; 26010037SARM gem5 Developers 26110037SARM gem5 Developers // Simply forward to the memory port 26210037SARM gem5 Developers cpuPorts[port].sendPacket(pkt); 26310037SARM gem5 Developers 26410037SARM gem5 Developers // For each of the cpu ports, if it needs to send a retry, it should do it 26510037SARM gem5 Developers // now since this memory object may be unblocked now. 26610037SARM gem5 Developers for (auto& port : cpuPorts) { 26710037SARM gem5 Developers port.trySendRetry(); 26810037SARM gem5 Developers } 26910037SARM gem5 Developers} 27010037SARM gem5 Developers 27110037SARM gem5 Developersvoid 27210037SARM gem5 DevelopersSimpleCache::handleFunctional(PacketPtr pkt) 27310037SARM gem5 Developers{ 27410037SARM gem5 Developers if (accessFunctional(pkt)) { 27510037SARM gem5 Developers pkt->makeResponse(); 27610037SARM gem5 Developers } else { 27710037SARM gem5 Developers memPort.sendFunctional(pkt); 27810037SARM gem5 Developers } 27910037SARM gem5 Developers} 28010037SARM gem5 Developers 28110037SARM gem5 Developersvoid 28210037SARM gem5 DevelopersSimpleCache::accessTiming(PacketPtr pkt) 28310037SARM gem5 Developers{ 28410037SARM gem5 Developers bool hit = accessFunctional(pkt); 28510037SARM gem5 Developers 28610037SARM gem5 Developers DPRINTF(SimpleCache, "%s for packet: %s\n", hit ? "Hit" : "Miss", 28710037SARM gem5 Developers pkt->print()); 28810037SARM gem5 Developers 28910037SARM gem5 Developers if (hit) { 29010037SARM gem5 Developers // Respond to the CPU side 29110037SARM gem5 Developers hits++; // update stats 29210037SARM gem5 Developers DDUMP(SimpleCache, pkt->getConstPtr<uint8_t>(), pkt->getSize()); 29310037SARM gem5 Developers pkt->makeResponse(); 29410037SARM gem5 Developers sendResponse(pkt); 29510037SARM gem5 Developers } else { 29610037SARM gem5 Developers misses++; // update stats 29710037SARM gem5 Developers missTime = curTick(); 29810037SARM gem5 Developers // Forward to the memory side. 29910037SARM gem5 Developers // We can't directly forward the packet unless it is exactly the size 30010037SARM gem5 Developers // of the cache line, and aligned. Check for that here. 30110037SARM gem5 Developers Addr addr = pkt->getAddr(); 30210037SARM gem5 Developers Addr block_addr = pkt->getBlockAddr(blockSize); 30310037SARM gem5 Developers unsigned size = pkt->getSize(); 30410037SARM gem5 Developers if (addr == block_addr && size == blockSize) { 30510037SARM gem5 Developers // Aligned and block size. We can just forward. 30610037SARM gem5 Developers DPRINTF(SimpleCache, "forwarding packet\n"); 30710037SARM gem5 Developers memPort.sendPacket(pkt); 30810037SARM gem5 Developers } else { 30910037SARM gem5 Developers DPRINTF(SimpleCache, "Upgrading packet to block size\n"); 31010037SARM gem5 Developers panic_if(addr - block_addr + size > blockSize, 31110037SARM gem5 Developers "Cannot handle accesses that span multiple cache lines"); 31210037SARM gem5 Developers // Unaligned access to one cache block 31310037SARM gem5 Developers assert(pkt->needsResponse()); 31410037SARM gem5 Developers MemCmd cmd; 31510037SARM gem5 Developers if (pkt->isWrite() || pkt->isRead()) { 31610037SARM gem5 Developers // Read the data from memory to write into the block. 31710037SARM gem5 Developers // We'll write the data in the cache (i.e., a writeback cache) 31810037SARM gem5 Developers cmd = MemCmd::ReadReq; 31910037SARM gem5 Developers } else { 32010037SARM gem5 Developers panic("Unknown packet type in upgrade size"); 32110037SARM gem5 Developers } 32210037SARM gem5 Developers 32310037SARM gem5 Developers // Create a new packet that is blockSize 32410037SARM gem5 Developers PacketPtr new_pkt = new Packet(pkt->req, cmd, blockSize); 32510037SARM gem5 Developers new_pkt->allocate(); 32610037SARM gem5 Developers 32710037SARM gem5 Developers // Should now be block aligned 32810037SARM gem5 Developers assert(new_pkt->getAddr() == new_pkt->getBlockAddr(blockSize)); 32910037SARM gem5 Developers 33010037SARM gem5 Developers // Save the old packet 33110037SARM gem5 Developers originalPacket = pkt; 33210037SARM gem5 Developers 33310037SARM gem5 Developers DPRINTF(SimpleCache, "forwarding packet\n"); 33410037SARM gem5 Developers memPort.sendPacket(new_pkt); 33510037SARM gem5 Developers } 33610037SARM gem5 Developers } 33710037SARM gem5 Developers} 33810037SARM gem5 Developers 33910037SARM gem5 Developersbool 34010037SARM gem5 DevelopersSimpleCache::accessFunctional(PacketPtr pkt) 34110037SARM gem5 Developers{ 34210037SARM gem5 Developers Addr block_addr = pkt->getBlockAddr(blockSize); 34310037SARM gem5 Developers auto it = cacheStore.find(block_addr); 34410037SARM gem5 Developers if (it != cacheStore.end()) { 34510037SARM gem5 Developers if (pkt->isWrite()) { 34610037SARM gem5 Developers // Write the data into the block in the cache 34710037SARM gem5 Developers pkt->writeDataToBlock(it->second, blockSize); 34810037SARM gem5 Developers } else if (pkt->isRead()) { 34910037SARM gem5 Developers // Read the data out of the cache block into the packet 35010037SARM gem5 Developers pkt->setDataFromBlock(it->second, blockSize); 35110037SARM gem5 Developers } else { 35210037SARM gem5 Developers panic("Unknown packet type!"); 35310037SARM gem5 Developers } 35410037SARM gem5 Developers return true; 35510037SARM gem5 Developers } 35610037SARM gem5 Developers return false; 35710037SARM gem5 Developers} 35810037SARM gem5 Developers 35910037SARM gem5 Developersvoid 36010037SARM gem5 DevelopersSimpleCache::insert(PacketPtr pkt) 36110037SARM gem5 Developers{ 36210037SARM gem5 Developers // The packet should be aligned. 36310037SARM gem5 Developers assert(pkt->getAddr() == pkt->getBlockAddr(blockSize)); 36410037SARM gem5 Developers // The address should not be in the cache 36510037SARM gem5 Developers assert(cacheStore.find(pkt->getAddr()) == cacheStore.end()); 36610037SARM gem5 Developers // The pkt should be a response 36710037SARM gem5 Developers assert(pkt->isResponse()); 36810037SARM gem5 Developers 36910037SARM gem5 Developers if (cacheStore.size() >= capacity) { 37010037SARM gem5 Developers // Select random thing to evict. This is a little convoluted since we 37110037SARM gem5 Developers // are using a std::unordered_map. See http://bit.ly/2hrnLP2 37210037SARM gem5 Developers int bucket, bucket_size; 37310037SARM gem5 Developers do { 37410037SARM gem5 Developers bucket = random_mt.random(0, (int)cacheStore.bucket_count() - 1); 37510037SARM gem5 Developers } while ( (bucket_size = cacheStore.bucket_size(bucket)) == 0 ); 37610037SARM gem5 Developers auto block = std::next(cacheStore.begin(bucket), 37710037SARM gem5 Developers random_mt.random(0, bucket_size - 1)); 37810037SARM gem5 Developers 37910037SARM gem5 Developers DPRINTF(SimpleCache, "Removing addr %#x\n", block->first); 38010037SARM gem5 Developers 38110037SARM gem5 Developers // Write back the data. 38210037SARM gem5 Developers // Create a new request-packet pair 38310037SARM gem5 Developers RequestPtr req = std::make_shared<Request>( 3847259Sgblack@eecs.umich.edu block->first, blockSize, 0, 0); 38510037SARM gem5 Developers 38610037SARM gem5 Developers PacketPtr new_pkt = new Packet(req, MemCmd::WritebackDirty, blockSize); 38710037SARM gem5 Developers new_pkt->dataDynamic(block->second); // This will be deleted later 38810037SARM gem5 Developers 38910037SARM gem5 Developers DPRINTF(SimpleCache, "Writing packet back %s\n", pkt->print()); 39010037SARM gem5 Developers // Send the write to memory 39110037SARM gem5 Developers memPort.sendPacket(new_pkt); 39210037SARM gem5 Developers 39310037SARM gem5 Developers // Delete this entry 39410037SARM gem5 Developers cacheStore.erase(block->first); 39510037SARM gem5 Developers } 39610037SARM gem5 Developers 39710037SARM gem5 Developers DPRINTF(SimpleCache, "Inserting %s\n", pkt->print()); 39810037SARM gem5 Developers DDUMP(SimpleCache, pkt->getConstPtr<uint8_t>(), blockSize); 39910037SARM gem5 Developers 40010037SARM gem5 Developers // Allocate space for the cache block data 40110037SARM gem5 Developers uint8_t *data = new uint8_t[blockSize]; 40210037SARM gem5 Developers 40310037SARM gem5 Developers // Insert the data and address into the cache store 40410037SARM gem5 Developers cacheStore[pkt->getAddr()] = data; 40510037SARM gem5 Developers 40610037SARM gem5 Developers // Write the data into the cache 40710037SARM gem5 Developers pkt->writeDataToBlock(data, blockSize); 40810037SARM gem5 Developers} 40910037SARM gem5 Developers 41010037SARM gem5 DevelopersAddrRangeList 41110037SARM gem5 DevelopersSimpleCache::getAddrRanges() const 41210037SARM gem5 Developers{ 41310037SARM gem5 Developers DPRINTF(SimpleCache, "Sending new ranges\n"); 41410037SARM gem5 Developers // Just use the same ranges as whatever is on the memory side. 41510037SARM gem5 Developers return memPort.getAddrRanges(); 41610037SARM gem5 Developers} 41710037SARM gem5 Developers 41810037SARM gem5 Developersvoid 41910037SARM gem5 DevelopersSimpleCache::sendRangeChange() const 42010037SARM gem5 Developers{ 42110037SARM gem5 Developers for (auto& port : cpuPorts) { 42210037SARM gem5 Developers port.sendRangeChange(); 42310037SARM gem5 Developers } 42411768SCurtis.Dunham@arm.com} 42511768SCurtis.Dunham@arm.com 4267259Sgblack@eecs.umich.eduvoid 42710037SARM gem5 DevelopersSimpleCache::regStats() 42810037SARM gem5 Developers{ 42910037SARM gem5 Developers // If you don't do this you get errors about uninitialized stats. 43010037SARM gem5 Developers ClockedObject::regStats(); 43110037SARM gem5 Developers 43210037SARM gem5 Developers hits.name(name() + ".hits") 43310037SARM gem5 Developers .desc("Number of hits") 43410037SARM gem5 Developers ; 43510037SARM gem5 Developers 43610037SARM gem5 Developers misses.name(name() + ".misses") 43710037SARM gem5 Developers .desc("Number of misses") 43810037SARM gem5 Developers ; 43910037SARM gem5 Developers 44010037SARM gem5 Developers missLatency.name(name() + ".missLatency") 44110037SARM gem5 Developers .desc("Ticks for misses to the cache") 44210037SARM gem5 Developers .init(16) // number of buckets 44310037SARM gem5 Developers ; 44410037SARM gem5 Developers 44510037SARM gem5 Developers hitRatio.name(name() + ".hitRatio") 44610037SARM gem5 Developers .desc("The ratio of hits to the total accesses to the cache") 44710037SARM gem5 Developers ; 44810037SARM gem5 Developers 44910037SARM gem5 Developers hitRatio = hits / (hits + misses); 45010037SARM gem5 Developers 45110037SARM gem5 Developers} 45210037SARM gem5 Developers 45310037SARM gem5 Developers 45410037SARM gem5 DevelopersSimpleCache* 45510037SARM gem5 DevelopersSimpleCacheParams::create() 45610037SARM gem5 Developers{ 45710037SARM gem5 Developers return new SimpleCache(this); 45810037SARM gem5 Developers} 45910037SARM gem5 Developers