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