simple_cache.cc revision 14252
112339Sjason@lowepower.com/* 212339Sjason@lowepower.com * Copyright (c) 2017 Jason Lowe-Power 312339Sjason@lowepower.com * All rights reserved. 412339Sjason@lowepower.com * 512339Sjason@lowepower.com * Redistribution and use in source and binary forms, with or without 612339Sjason@lowepower.com * modification, are permitted provided that the following conditions are 712339Sjason@lowepower.com * met: redistributions of source code must retain the above copyright 812339Sjason@lowepower.com * notice, this list of conditions and the following disclaimer; 912339Sjason@lowepower.com * redistributions in binary form must reproduce the above copyright 1012339Sjason@lowepower.com * notice, this list of conditions and the following disclaimer in the 1112339Sjason@lowepower.com * documentation and/or other materials provided with the distribution; 1212339Sjason@lowepower.com * neither the name of the copyright holders nor the names of its 1312339Sjason@lowepower.com * contributors may be used to endorse or promote products derived from 1412339Sjason@lowepower.com * this software without specific prior written permission. 1512339Sjason@lowepower.com * 1612339Sjason@lowepower.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712339Sjason@lowepower.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812339Sjason@lowepower.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912339Sjason@lowepower.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012339Sjason@lowepower.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112339Sjason@lowepower.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212339Sjason@lowepower.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312339Sjason@lowepower.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412339Sjason@lowepower.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512339Sjason@lowepower.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612339Sjason@lowepower.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712339Sjason@lowepower.com * 2812339Sjason@lowepower.com * Authors: Jason Lowe-Power 2912339Sjason@lowepower.com */ 3012339Sjason@lowepower.com 3112339Sjason@lowepower.com#include "learning_gem5/part2/simple_cache.hh" 3212339Sjason@lowepower.com 3312339Sjason@lowepower.com#include "base/random.hh" 3412339Sjason@lowepower.com#include "debug/SimpleCache.hh" 3512339Sjason@lowepower.com#include "sim/system.hh" 3612339Sjason@lowepower.com 3712339Sjason@lowepower.comSimpleCache::SimpleCache(SimpleCacheParams *params) : 3814252Sgabeblack@google.com ClockedObject(params), 3912339Sjason@lowepower.com latency(params->latency), 4012339Sjason@lowepower.com blockSize(params->system->cacheLineSize()), 4112339Sjason@lowepower.com capacity(params->size / blockSize), 4212339Sjason@lowepower.com memPort(params->name + ".mem_side", this), 4312339Sjason@lowepower.com blocked(false), originalPacket(nullptr), waitingPortId(-1) 4412339Sjason@lowepower.com{ 4512339Sjason@lowepower.com // Since the CPU side ports are a vector of ports, create an instance of 4612339Sjason@lowepower.com // the CPUSidePort for each connection. This member of params is 4712339Sjason@lowepower.com // automatically created depending on the name of the vector port and 4812339Sjason@lowepower.com // holds the number of connections to this port name 4912339Sjason@lowepower.com for (int i = 0; i < params->port_cpu_side_connection_count; ++i) { 5012339Sjason@lowepower.com cpuPorts.emplace_back(name() + csprintf(".cpu_side[%d]", i), i, this); 5112339Sjason@lowepower.com } 5212339Sjason@lowepower.com} 5312339Sjason@lowepower.com 5413784Sgabeblack@google.comPort & 5513784Sgabeblack@google.comSimpleCache::getPort(const std::string &if_name, PortID idx) 5612339Sjason@lowepower.com{ 5712339Sjason@lowepower.com // This is the name from the Python SimObject declaration in SimpleCache.py 5812339Sjason@lowepower.com if (if_name == "mem_side") { 5913841Sjason@lowepower.com panic_if(idx != InvalidPortID, 6013841Sjason@lowepower.com "Mem side of simple cache not a vector port"); 6112339Sjason@lowepower.com return memPort; 6213784Sgabeblack@google.com } else if (if_name == "cpu_side" && idx < cpuPorts.size()) { 6312339Sjason@lowepower.com // We should have already created all of the ports in the constructor 6412339Sjason@lowepower.com return cpuPorts[idx]; 6512339Sjason@lowepower.com } else { 6612339Sjason@lowepower.com // pass it along to our super class 6714252Sgabeblack@google.com return ClockedObject::getPort(if_name, idx); 6812339Sjason@lowepower.com } 6912339Sjason@lowepower.com} 7012339Sjason@lowepower.com 7112339Sjason@lowepower.comvoid 7212339Sjason@lowepower.comSimpleCache::CPUSidePort::sendPacket(PacketPtr pkt) 7312339Sjason@lowepower.com{ 7412339Sjason@lowepower.com // Note: This flow control is very simple since the cache is blocking. 7512339Sjason@lowepower.com 7612339Sjason@lowepower.com panic_if(blockedPacket != nullptr, "Should never try to send if blocked!"); 7712339Sjason@lowepower.com 7812339Sjason@lowepower.com // If we can't send the packet across the port, store it for later. 7912339Sjason@lowepower.com DPRINTF(SimpleCache, "Sending %s to CPU\n", pkt->print()); 8012339Sjason@lowepower.com if (!sendTimingResp(pkt)) { 8112339Sjason@lowepower.com DPRINTF(SimpleCache, "failed!\n"); 8212339Sjason@lowepower.com blockedPacket = pkt; 8312339Sjason@lowepower.com } 8412339Sjason@lowepower.com} 8512339Sjason@lowepower.com 8612339Sjason@lowepower.comAddrRangeList 8712339Sjason@lowepower.comSimpleCache::CPUSidePort::getAddrRanges() const 8812339Sjason@lowepower.com{ 8912339Sjason@lowepower.com return owner->getAddrRanges(); 9012339Sjason@lowepower.com} 9112339Sjason@lowepower.com 9212339Sjason@lowepower.comvoid 9312339Sjason@lowepower.comSimpleCache::CPUSidePort::trySendRetry() 9412339Sjason@lowepower.com{ 9512339Sjason@lowepower.com if (needRetry && blockedPacket == nullptr) { 9612339Sjason@lowepower.com // Only send a retry if the port is now completely free 9712339Sjason@lowepower.com needRetry = false; 9812339Sjason@lowepower.com DPRINTF(SimpleCache, "Sending retry req.\n"); 9912339Sjason@lowepower.com sendRetryReq(); 10012339Sjason@lowepower.com } 10112339Sjason@lowepower.com} 10212339Sjason@lowepower.com 10312339Sjason@lowepower.comvoid 10412339Sjason@lowepower.comSimpleCache::CPUSidePort::recvFunctional(PacketPtr pkt) 10512339Sjason@lowepower.com{ 10612339Sjason@lowepower.com // Just forward to the cache. 10712339Sjason@lowepower.com return owner->handleFunctional(pkt); 10812339Sjason@lowepower.com} 10912339Sjason@lowepower.com 11012339Sjason@lowepower.combool 11112339Sjason@lowepower.comSimpleCache::CPUSidePort::recvTimingReq(PacketPtr pkt) 11212339Sjason@lowepower.com{ 11312339Sjason@lowepower.com DPRINTF(SimpleCache, "Got request %s\n", pkt->print()); 11412339Sjason@lowepower.com 11512339Sjason@lowepower.com if (blockedPacket || needRetry) { 11612339Sjason@lowepower.com // The cache may not be able to send a reply if this is blocked 11712339Sjason@lowepower.com DPRINTF(SimpleCache, "Request blocked\n"); 11812339Sjason@lowepower.com needRetry = true; 11912339Sjason@lowepower.com return false; 12012339Sjason@lowepower.com } 12112339Sjason@lowepower.com // Just forward to the cache. 12212339Sjason@lowepower.com if (!owner->handleRequest(pkt, id)) { 12312339Sjason@lowepower.com DPRINTF(SimpleCache, "Request failed\n"); 12412339Sjason@lowepower.com // stalling 12512339Sjason@lowepower.com needRetry = true; 12612339Sjason@lowepower.com return false; 12712339Sjason@lowepower.com } else { 12812339Sjason@lowepower.com DPRINTF(SimpleCache, "Request succeeded\n"); 12912339Sjason@lowepower.com return true; 13012339Sjason@lowepower.com } 13112339Sjason@lowepower.com} 13212339Sjason@lowepower.com 13312339Sjason@lowepower.comvoid 13412339Sjason@lowepower.comSimpleCache::CPUSidePort::recvRespRetry() 13512339Sjason@lowepower.com{ 13612339Sjason@lowepower.com // We should have a blocked packet if this function is called. 13712339Sjason@lowepower.com assert(blockedPacket != nullptr); 13812339Sjason@lowepower.com 13912339Sjason@lowepower.com // Grab the blocked packet. 14012339Sjason@lowepower.com PacketPtr pkt = blockedPacket; 14112339Sjason@lowepower.com blockedPacket = nullptr; 14212339Sjason@lowepower.com 14312339Sjason@lowepower.com DPRINTF(SimpleCache, "Retrying response pkt %s\n", pkt->print()); 14412339Sjason@lowepower.com // Try to resend it. It's possible that it fails again. 14512339Sjason@lowepower.com sendPacket(pkt); 14612339Sjason@lowepower.com 14712339Sjason@lowepower.com // We may now be able to accept new packets 14812339Sjason@lowepower.com trySendRetry(); 14912339Sjason@lowepower.com} 15012339Sjason@lowepower.com 15112339Sjason@lowepower.comvoid 15212339Sjason@lowepower.comSimpleCache::MemSidePort::sendPacket(PacketPtr pkt) 15312339Sjason@lowepower.com{ 15412339Sjason@lowepower.com // Note: This flow control is very simple since the cache is blocking. 15512339Sjason@lowepower.com 15612339Sjason@lowepower.com panic_if(blockedPacket != nullptr, "Should never try to send if blocked!"); 15712339Sjason@lowepower.com 15812339Sjason@lowepower.com // If we can't send the packet across the port, store it for later. 15912339Sjason@lowepower.com if (!sendTimingReq(pkt)) { 16012339Sjason@lowepower.com blockedPacket = pkt; 16112339Sjason@lowepower.com } 16212339Sjason@lowepower.com} 16312339Sjason@lowepower.com 16412339Sjason@lowepower.combool 16512339Sjason@lowepower.comSimpleCache::MemSidePort::recvTimingResp(PacketPtr pkt) 16612339Sjason@lowepower.com{ 16712339Sjason@lowepower.com // Just forward to the cache. 16812339Sjason@lowepower.com return owner->handleResponse(pkt); 16912339Sjason@lowepower.com} 17012339Sjason@lowepower.com 17112339Sjason@lowepower.comvoid 17212339Sjason@lowepower.comSimpleCache::MemSidePort::recvReqRetry() 17312339Sjason@lowepower.com{ 17412339Sjason@lowepower.com // We should have a blocked packet if this function is called. 17512339Sjason@lowepower.com assert(blockedPacket != nullptr); 17612339Sjason@lowepower.com 17712339Sjason@lowepower.com // Grab the blocked packet. 17812339Sjason@lowepower.com PacketPtr pkt = blockedPacket; 17912339Sjason@lowepower.com blockedPacket = nullptr; 18012339Sjason@lowepower.com 18112339Sjason@lowepower.com // Try to resend it. It's possible that it fails again. 18212339Sjason@lowepower.com sendPacket(pkt); 18312339Sjason@lowepower.com} 18412339Sjason@lowepower.com 18512339Sjason@lowepower.comvoid 18612339Sjason@lowepower.comSimpleCache::MemSidePort::recvRangeChange() 18712339Sjason@lowepower.com{ 18812339Sjason@lowepower.com owner->sendRangeChange(); 18912339Sjason@lowepower.com} 19012339Sjason@lowepower.com 19112339Sjason@lowepower.combool 19212339Sjason@lowepower.comSimpleCache::handleRequest(PacketPtr pkt, int port_id) 19312339Sjason@lowepower.com{ 19412339Sjason@lowepower.com if (blocked) { 19512339Sjason@lowepower.com // There is currently an outstanding request so we can't respond. Stall 19612339Sjason@lowepower.com return false; 19712339Sjason@lowepower.com } 19812339Sjason@lowepower.com 19912339Sjason@lowepower.com DPRINTF(SimpleCache, "Got request for addr %#x\n", pkt->getAddr()); 20012339Sjason@lowepower.com 20112339Sjason@lowepower.com // This cache is now blocked waiting for the response to this packet. 20212339Sjason@lowepower.com blocked = true; 20312339Sjason@lowepower.com 20412339Sjason@lowepower.com // Store the port for when we get the response 20512339Sjason@lowepower.com assert(waitingPortId == -1); 20612339Sjason@lowepower.com waitingPortId = port_id; 20712339Sjason@lowepower.com 20812339Sjason@lowepower.com // Schedule an event after cache access latency to actually access 20912339Sjason@lowepower.com schedule(new EventFunctionWrapper([this, pkt]{ accessTiming(pkt); }, 21012339Sjason@lowepower.com name() + ".accessEvent", true), 21112339Sjason@lowepower.com clockEdge(latency)); 21212339Sjason@lowepower.com 21312339Sjason@lowepower.com return true; 21412339Sjason@lowepower.com} 21512339Sjason@lowepower.com 21612339Sjason@lowepower.combool 21712339Sjason@lowepower.comSimpleCache::handleResponse(PacketPtr pkt) 21812339Sjason@lowepower.com{ 21912339Sjason@lowepower.com assert(blocked); 22012339Sjason@lowepower.com DPRINTF(SimpleCache, "Got response for addr %#x\n", pkt->getAddr()); 22112339Sjason@lowepower.com 22212339Sjason@lowepower.com // For now assume that inserts are off of the critical path and don't count 22312339Sjason@lowepower.com // for any added latency. 22412339Sjason@lowepower.com insert(pkt); 22512339Sjason@lowepower.com 22612339Sjason@lowepower.com missLatency.sample(curTick() - missTime); 22712339Sjason@lowepower.com 22812339Sjason@lowepower.com // If we had to upgrade the request packet to a full cache line, now we 22912339Sjason@lowepower.com // can use that packet to construct the response. 23012339Sjason@lowepower.com if (originalPacket != nullptr) { 23112339Sjason@lowepower.com DPRINTF(SimpleCache, "Copying data from new packet to old\n"); 23212339Sjason@lowepower.com // We had to upgrade a previous packet. We can functionally deal with 23312339Sjason@lowepower.com // the cache access now. It better be a hit. 23412339Sjason@lowepower.com bool hit M5_VAR_USED = accessFunctional(originalPacket); 23512339Sjason@lowepower.com panic_if(!hit, "Should always hit after inserting"); 23612339Sjason@lowepower.com originalPacket->makeResponse(); 23712339Sjason@lowepower.com delete pkt; // We may need to delay this, I'm not sure. 23812339Sjason@lowepower.com pkt = originalPacket; 23912339Sjason@lowepower.com originalPacket = nullptr; 24012339Sjason@lowepower.com } // else, pkt contains the data it needs 24112339Sjason@lowepower.com 24212339Sjason@lowepower.com sendResponse(pkt); 24312339Sjason@lowepower.com 24412339Sjason@lowepower.com return true; 24512339Sjason@lowepower.com} 24612339Sjason@lowepower.com 24712339Sjason@lowepower.comvoid SimpleCache::sendResponse(PacketPtr pkt) 24812339Sjason@lowepower.com{ 24912339Sjason@lowepower.com assert(blocked); 25012339Sjason@lowepower.com DPRINTF(SimpleCache, "Sending resp for addr %#x\n", pkt->getAddr()); 25112339Sjason@lowepower.com 25212339Sjason@lowepower.com int port = waitingPortId; 25312339Sjason@lowepower.com 25412339Sjason@lowepower.com // The packet is now done. We're about to put it in the port, no need for 25512339Sjason@lowepower.com // this object to continue to stall. 25612339Sjason@lowepower.com // We need to free the resource before sending the packet in case the CPU 25712339Sjason@lowepower.com // tries to send another request immediately (e.g., in the same callchain). 25812339Sjason@lowepower.com blocked = false; 25912339Sjason@lowepower.com waitingPortId = -1; 26012339Sjason@lowepower.com 26112339Sjason@lowepower.com // Simply forward to the memory port 26212339Sjason@lowepower.com cpuPorts[port].sendPacket(pkt); 26312339Sjason@lowepower.com 26412339Sjason@lowepower.com // For each of the cpu ports, if it needs to send a retry, it should do it 26512339Sjason@lowepower.com // now since this memory object may be unblocked now. 26612339Sjason@lowepower.com for (auto& port : cpuPorts) { 26712339Sjason@lowepower.com port.trySendRetry(); 26812339Sjason@lowepower.com } 26912339Sjason@lowepower.com} 27012339Sjason@lowepower.com 27112339Sjason@lowepower.comvoid 27212339Sjason@lowepower.comSimpleCache::handleFunctional(PacketPtr pkt) 27312339Sjason@lowepower.com{ 27412339Sjason@lowepower.com if (accessFunctional(pkt)) { 27512339Sjason@lowepower.com pkt->makeResponse(); 27612339Sjason@lowepower.com } else { 27712339Sjason@lowepower.com memPort.sendFunctional(pkt); 27812339Sjason@lowepower.com } 27912339Sjason@lowepower.com} 28012339Sjason@lowepower.com 28112339Sjason@lowepower.comvoid 28212339Sjason@lowepower.comSimpleCache::accessTiming(PacketPtr pkt) 28312339Sjason@lowepower.com{ 28412339Sjason@lowepower.com bool hit = accessFunctional(pkt); 28512339Sjason@lowepower.com 28612339Sjason@lowepower.com DPRINTF(SimpleCache, "%s for packet: %s\n", hit ? "Hit" : "Miss", 28712339Sjason@lowepower.com pkt->print()); 28812339Sjason@lowepower.com 28912339Sjason@lowepower.com if (hit) { 29012339Sjason@lowepower.com // Respond to the CPU side 29112339Sjason@lowepower.com hits++; // update stats 29212339Sjason@lowepower.com DDUMP(SimpleCache, pkt->getConstPtr<uint8_t>(), pkt->getSize()); 29312339Sjason@lowepower.com pkt->makeResponse(); 29412339Sjason@lowepower.com sendResponse(pkt); 29512339Sjason@lowepower.com } else { 29612339Sjason@lowepower.com misses++; // update stats 29712339Sjason@lowepower.com missTime = curTick(); 29812339Sjason@lowepower.com // Forward to the memory side. 29912339Sjason@lowepower.com // We can't directly forward the packet unless it is exactly the size 30012339Sjason@lowepower.com // of the cache line, and aligned. Check for that here. 30112339Sjason@lowepower.com Addr addr = pkt->getAddr(); 30212339Sjason@lowepower.com Addr block_addr = pkt->getBlockAddr(blockSize); 30312339Sjason@lowepower.com unsigned size = pkt->getSize(); 30412339Sjason@lowepower.com if (addr == block_addr && size == blockSize) { 30512339Sjason@lowepower.com // Aligned and block size. We can just forward. 30612339Sjason@lowepower.com DPRINTF(SimpleCache, "forwarding packet\n"); 30712339Sjason@lowepower.com memPort.sendPacket(pkt); 30812339Sjason@lowepower.com } else { 30912339Sjason@lowepower.com DPRINTF(SimpleCache, "Upgrading packet to block size\n"); 31012339Sjason@lowepower.com panic_if(addr - block_addr + size > blockSize, 31112339Sjason@lowepower.com "Cannot handle accesses that span multiple cache lines"); 31212339Sjason@lowepower.com // Unaligned access to one cache block 31312339Sjason@lowepower.com assert(pkt->needsResponse()); 31412339Sjason@lowepower.com MemCmd cmd; 31512339Sjason@lowepower.com if (pkt->isWrite() || pkt->isRead()) { 31612339Sjason@lowepower.com // Read the data from memory to write into the block. 31712339Sjason@lowepower.com // We'll write the data in the cache (i.e., a writeback cache) 31812339Sjason@lowepower.com cmd = MemCmd::ReadReq; 31912339Sjason@lowepower.com } else { 32012339Sjason@lowepower.com panic("Unknown packet type in upgrade size"); 32112339Sjason@lowepower.com } 32212339Sjason@lowepower.com 32312339Sjason@lowepower.com // Create a new packet that is blockSize 32412339Sjason@lowepower.com PacketPtr new_pkt = new Packet(pkt->req, cmd, blockSize); 32512339Sjason@lowepower.com new_pkt->allocate(); 32612339Sjason@lowepower.com 32712339Sjason@lowepower.com // Should now be block aligned 32812339Sjason@lowepower.com assert(new_pkt->getAddr() == new_pkt->getBlockAddr(blockSize)); 32912339Sjason@lowepower.com 33012339Sjason@lowepower.com // Save the old packet 33112339Sjason@lowepower.com originalPacket = pkt; 33212339Sjason@lowepower.com 33312339Sjason@lowepower.com DPRINTF(SimpleCache, "forwarding packet\n"); 33412339Sjason@lowepower.com memPort.sendPacket(new_pkt); 33512339Sjason@lowepower.com } 33612339Sjason@lowepower.com } 33712339Sjason@lowepower.com} 33812339Sjason@lowepower.com 33912339Sjason@lowepower.combool 34012339Sjason@lowepower.comSimpleCache::accessFunctional(PacketPtr pkt) 34112339Sjason@lowepower.com{ 34212339Sjason@lowepower.com Addr block_addr = pkt->getBlockAddr(blockSize); 34312339Sjason@lowepower.com auto it = cacheStore.find(block_addr); 34412339Sjason@lowepower.com if (it != cacheStore.end()) { 34512339Sjason@lowepower.com if (pkt->isWrite()) { 34612339Sjason@lowepower.com // Write the data into the block in the cache 34712339Sjason@lowepower.com pkt->writeDataToBlock(it->second, blockSize); 34812339Sjason@lowepower.com } else if (pkt->isRead()) { 34912339Sjason@lowepower.com // Read the data out of the cache block into the packet 35012339Sjason@lowepower.com pkt->setDataFromBlock(it->second, blockSize); 35112339Sjason@lowepower.com } else { 35212339Sjason@lowepower.com panic("Unknown packet type!"); 35312339Sjason@lowepower.com } 35412339Sjason@lowepower.com return true; 35512339Sjason@lowepower.com } 35612339Sjason@lowepower.com return false; 35712339Sjason@lowepower.com} 35812339Sjason@lowepower.com 35912339Sjason@lowepower.comvoid 36012339Sjason@lowepower.comSimpleCache::insert(PacketPtr pkt) 36112339Sjason@lowepower.com{ 36212339Sjason@lowepower.com // The packet should be aligned. 36312339Sjason@lowepower.com assert(pkt->getAddr() == pkt->getBlockAddr(blockSize)); 36412339Sjason@lowepower.com // The address should not be in the cache 36512339Sjason@lowepower.com assert(cacheStore.find(pkt->getAddr()) == cacheStore.end()); 36612339Sjason@lowepower.com // The pkt should be a response 36712339Sjason@lowepower.com assert(pkt->isResponse()); 36812339Sjason@lowepower.com 36912339Sjason@lowepower.com if (cacheStore.size() >= capacity) { 37012339Sjason@lowepower.com // Select random thing to evict. This is a little convoluted since we 37112339Sjason@lowepower.com // are using a std::unordered_map. See http://bit.ly/2hrnLP2 37212339Sjason@lowepower.com int bucket, bucket_size; 37312339Sjason@lowepower.com do { 37412339Sjason@lowepower.com bucket = random_mt.random(0, (int)cacheStore.bucket_count() - 1); 37512339Sjason@lowepower.com } while ( (bucket_size = cacheStore.bucket_size(bucket)) == 0 ); 37612339Sjason@lowepower.com auto block = std::next(cacheStore.begin(bucket), 37712339Sjason@lowepower.com random_mt.random(0, bucket_size - 1)); 37812339Sjason@lowepower.com 37912339Sjason@lowepower.com DPRINTF(SimpleCache, "Removing addr %#x\n", block->first); 38012339Sjason@lowepower.com 38112339Sjason@lowepower.com // Write back the data. 38212339Sjason@lowepower.com // Create a new request-packet pair 38312749Sgiacomo.travaglini@arm.com RequestPtr req = std::make_shared<Request>( 38412749Sgiacomo.travaglini@arm.com block->first, blockSize, 0, 0); 38512749Sgiacomo.travaglini@arm.com 38612339Sjason@lowepower.com PacketPtr new_pkt = new Packet(req, MemCmd::WritebackDirty, blockSize); 38712339Sjason@lowepower.com new_pkt->dataDynamic(block->second); // This will be deleted later 38812339Sjason@lowepower.com 38912339Sjason@lowepower.com DPRINTF(SimpleCache, "Writing packet back %s\n", pkt->print()); 39012339Sjason@lowepower.com // Send the write to memory 39112339Sjason@lowepower.com memPort.sendPacket(new_pkt); 39212339Sjason@lowepower.com 39312339Sjason@lowepower.com // Delete this entry 39412339Sjason@lowepower.com cacheStore.erase(block->first); 39512339Sjason@lowepower.com } 39612339Sjason@lowepower.com 39712339Sjason@lowepower.com DPRINTF(SimpleCache, "Inserting %s\n", pkt->print()); 39812339Sjason@lowepower.com DDUMP(SimpleCache, pkt->getConstPtr<uint8_t>(), blockSize); 39912339Sjason@lowepower.com 40012339Sjason@lowepower.com // Allocate space for the cache block data 40112339Sjason@lowepower.com uint8_t *data = new uint8_t[blockSize]; 40212339Sjason@lowepower.com 40312339Sjason@lowepower.com // Insert the data and address into the cache store 40412339Sjason@lowepower.com cacheStore[pkt->getAddr()] = data; 40512339Sjason@lowepower.com 40612339Sjason@lowepower.com // Write the data into the cache 40712339Sjason@lowepower.com pkt->writeDataToBlock(data, blockSize); 40812339Sjason@lowepower.com} 40912339Sjason@lowepower.com 41012339Sjason@lowepower.comAddrRangeList 41112339Sjason@lowepower.comSimpleCache::getAddrRanges() const 41212339Sjason@lowepower.com{ 41312339Sjason@lowepower.com DPRINTF(SimpleCache, "Sending new ranges\n"); 41412339Sjason@lowepower.com // Just use the same ranges as whatever is on the memory side. 41512339Sjason@lowepower.com return memPort.getAddrRanges(); 41612339Sjason@lowepower.com} 41712339Sjason@lowepower.com 41812339Sjason@lowepower.comvoid 41912339Sjason@lowepower.comSimpleCache::sendRangeChange() const 42012339Sjason@lowepower.com{ 42112339Sjason@lowepower.com for (auto& port : cpuPorts) { 42212339Sjason@lowepower.com port.sendRangeChange(); 42312339Sjason@lowepower.com } 42412339Sjason@lowepower.com} 42512339Sjason@lowepower.com 42612339Sjason@lowepower.comvoid 42712339Sjason@lowepower.comSimpleCache::regStats() 42812339Sjason@lowepower.com{ 42912339Sjason@lowepower.com // If you don't do this you get errors about uninitialized stats. 43014252Sgabeblack@google.com ClockedObject::regStats(); 43112339Sjason@lowepower.com 43212339Sjason@lowepower.com hits.name(name() + ".hits") 43312339Sjason@lowepower.com .desc("Number of hits") 43412339Sjason@lowepower.com ; 43512339Sjason@lowepower.com 43612339Sjason@lowepower.com misses.name(name() + ".misses") 43712339Sjason@lowepower.com .desc("Number of misses") 43812339Sjason@lowepower.com ; 43912339Sjason@lowepower.com 44012339Sjason@lowepower.com missLatency.name(name() + ".missLatency") 44112339Sjason@lowepower.com .desc("Ticks for misses to the cache") 44212339Sjason@lowepower.com .init(16) // number of buckets 44312339Sjason@lowepower.com ; 44412339Sjason@lowepower.com 44512339Sjason@lowepower.com hitRatio.name(name() + ".hitRatio") 44612339Sjason@lowepower.com .desc("The ratio of hits to the total accesses to the cache") 44712339Sjason@lowepower.com ; 44812339Sjason@lowepower.com 44912339Sjason@lowepower.com hitRatio = hits / (hits + misses); 45012339Sjason@lowepower.com 45112339Sjason@lowepower.com} 45212339Sjason@lowepower.com 45312339Sjason@lowepower.com 45412339Sjason@lowepower.comSimpleCache* 45512339Sjason@lowepower.comSimpleCacheParams::create() 45612339Sjason@lowepower.com{ 45712339Sjason@lowepower.com return new SimpleCache(this); 45812339Sjason@lowepower.com} 459