simple_cache.hh revision 13784
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#ifndef __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__ 3212339Sjason@lowepower.com#define __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__ 3312339Sjason@lowepower.com 3412339Sjason@lowepower.com#include <unordered_map> 3512339Sjason@lowepower.com 3612339Sjason@lowepower.com#include "mem/mem_object.hh" 3712339Sjason@lowepower.com#include "params/SimpleCache.hh" 3812339Sjason@lowepower.com 3912339Sjason@lowepower.com/** 4012339Sjason@lowepower.com * A very simple cache object. Has a fully-associative data store with random 4112339Sjason@lowepower.com * replacement. 4212339Sjason@lowepower.com * This cache is fully blocking (not non-blocking). Only a single request can 4312339Sjason@lowepower.com * be outstanding at a time. 4412339Sjason@lowepower.com * This cache is a writeback cache. 4512339Sjason@lowepower.com */ 4612339Sjason@lowepower.comclass SimpleCache : public MemObject 4712339Sjason@lowepower.com{ 4812339Sjason@lowepower.com private: 4912339Sjason@lowepower.com 5012339Sjason@lowepower.com /** 5112339Sjason@lowepower.com * Port on the CPU-side that receives requests. 5212339Sjason@lowepower.com * Mostly just forwards requests to the cache (owner) 5312339Sjason@lowepower.com */ 5412339Sjason@lowepower.com class CPUSidePort : public SlavePort 5512339Sjason@lowepower.com { 5612339Sjason@lowepower.com private: 5712339Sjason@lowepower.com /// Since this is a vector port, need to know what number this one is 5812339Sjason@lowepower.com int id; 5912339Sjason@lowepower.com 6012339Sjason@lowepower.com /// The object that owns this object (SimpleCache) 6112339Sjason@lowepower.com SimpleCache *owner; 6212339Sjason@lowepower.com 6312339Sjason@lowepower.com /// True if the port needs to send a retry req. 6412339Sjason@lowepower.com bool needRetry; 6512339Sjason@lowepower.com 6612339Sjason@lowepower.com /// If we tried to send a packet and it was blocked, store it here 6712339Sjason@lowepower.com PacketPtr blockedPacket; 6812339Sjason@lowepower.com 6912339Sjason@lowepower.com public: 7012339Sjason@lowepower.com /** 7112339Sjason@lowepower.com * Constructor. Just calls the superclass constructor. 7212339Sjason@lowepower.com */ 7312339Sjason@lowepower.com CPUSidePort(const std::string& name, int id, SimpleCache *owner) : 7412339Sjason@lowepower.com SlavePort(name, owner), id(id), owner(owner), needRetry(false), 7512339Sjason@lowepower.com blockedPacket(nullptr) 7612339Sjason@lowepower.com { } 7712339Sjason@lowepower.com 7812339Sjason@lowepower.com /** 7912339Sjason@lowepower.com * Send a packet across this port. This is called by the owner and 8012339Sjason@lowepower.com * all of the flow control is hanled in this function. 8112339Sjason@lowepower.com * This is a convenience function for the SimpleCache to send pkts. 8212339Sjason@lowepower.com * 8312339Sjason@lowepower.com * @param packet to send. 8412339Sjason@lowepower.com */ 8512339Sjason@lowepower.com void sendPacket(PacketPtr pkt); 8612339Sjason@lowepower.com 8712339Sjason@lowepower.com /** 8812339Sjason@lowepower.com * Get a list of the non-overlapping address ranges the owner is 8912339Sjason@lowepower.com * responsible for. All slave ports must override this function 9012339Sjason@lowepower.com * and return a populated list with at least one item. 9112339Sjason@lowepower.com * 9212339Sjason@lowepower.com * @return a list of ranges responded to 9312339Sjason@lowepower.com */ 9412339Sjason@lowepower.com AddrRangeList getAddrRanges() const override; 9512339Sjason@lowepower.com 9612339Sjason@lowepower.com /** 9712339Sjason@lowepower.com * Send a retry to the peer port only if it is needed. This is called 9812339Sjason@lowepower.com * from the SimpleCache whenever it is unblocked. 9912339Sjason@lowepower.com */ 10012339Sjason@lowepower.com void trySendRetry(); 10112339Sjason@lowepower.com 10212339Sjason@lowepower.com protected: 10312339Sjason@lowepower.com /** 10412339Sjason@lowepower.com * Receive an atomic request packet from the master port. 10512339Sjason@lowepower.com * No need to implement in this simple cache. 10612339Sjason@lowepower.com */ 10712339Sjason@lowepower.com Tick recvAtomic(PacketPtr pkt) override 10812339Sjason@lowepower.com { panic("recvAtomic unimpl."); } 10912339Sjason@lowepower.com 11012339Sjason@lowepower.com /** 11112339Sjason@lowepower.com * Receive a functional request packet from the master port. 11212339Sjason@lowepower.com * Performs a "debug" access updating/reading the data in place. 11312339Sjason@lowepower.com * 11412339Sjason@lowepower.com * @param packet the requestor sent. 11512339Sjason@lowepower.com */ 11612339Sjason@lowepower.com void recvFunctional(PacketPtr pkt) override; 11712339Sjason@lowepower.com 11812339Sjason@lowepower.com /** 11912339Sjason@lowepower.com * Receive a timing request from the master port. 12012339Sjason@lowepower.com * 12112339Sjason@lowepower.com * @param the packet that the requestor sent 12212339Sjason@lowepower.com * @return whether this object can consume to packet. If false, we 12312339Sjason@lowepower.com * will call sendRetry() when we can try to receive this 12412339Sjason@lowepower.com * request again. 12512339Sjason@lowepower.com */ 12612339Sjason@lowepower.com bool recvTimingReq(PacketPtr pkt) override; 12712339Sjason@lowepower.com 12812339Sjason@lowepower.com /** 12912339Sjason@lowepower.com * Called by the master port if sendTimingResp was called on this 13012339Sjason@lowepower.com * slave port (causing recvTimingResp to be called on the master 13112339Sjason@lowepower.com * port) and was unsuccesful. 13212339Sjason@lowepower.com */ 13312339Sjason@lowepower.com void recvRespRetry() override; 13412339Sjason@lowepower.com }; 13512339Sjason@lowepower.com 13612339Sjason@lowepower.com /** 13712339Sjason@lowepower.com * Port on the memory-side that receives responses. 13812339Sjason@lowepower.com * Mostly just forwards requests to the cache (owner) 13912339Sjason@lowepower.com */ 14012339Sjason@lowepower.com class MemSidePort : public MasterPort 14112339Sjason@lowepower.com { 14212339Sjason@lowepower.com private: 14312339Sjason@lowepower.com /// The object that owns this object (SimpleCache) 14412339Sjason@lowepower.com SimpleCache *owner; 14512339Sjason@lowepower.com 14612339Sjason@lowepower.com /// If we tried to send a packet and it was blocked, store it here 14712339Sjason@lowepower.com PacketPtr blockedPacket; 14812339Sjason@lowepower.com 14912339Sjason@lowepower.com public: 15012339Sjason@lowepower.com /** 15112339Sjason@lowepower.com * Constructor. Just calls the superclass constructor. 15212339Sjason@lowepower.com */ 15312339Sjason@lowepower.com MemSidePort(const std::string& name, SimpleCache *owner) : 15412339Sjason@lowepower.com MasterPort(name, owner), owner(owner), blockedPacket(nullptr) 15512339Sjason@lowepower.com { } 15612339Sjason@lowepower.com 15712339Sjason@lowepower.com /** 15812339Sjason@lowepower.com * Send a packet across this port. This is called by the owner and 15912339Sjason@lowepower.com * all of the flow control is hanled in this function. 16012339Sjason@lowepower.com * This is a convenience function for the SimpleCache to send pkts. 16112339Sjason@lowepower.com * 16212339Sjason@lowepower.com * @param packet to send. 16312339Sjason@lowepower.com */ 16412339Sjason@lowepower.com void sendPacket(PacketPtr pkt); 16512339Sjason@lowepower.com 16612339Sjason@lowepower.com protected: 16712339Sjason@lowepower.com /** 16812339Sjason@lowepower.com * Receive a timing response from the slave port. 16912339Sjason@lowepower.com */ 17012339Sjason@lowepower.com bool recvTimingResp(PacketPtr pkt) override; 17112339Sjason@lowepower.com 17212339Sjason@lowepower.com /** 17312339Sjason@lowepower.com * Called by the slave port if sendTimingReq was called on this 17412339Sjason@lowepower.com * master port (causing recvTimingReq to be called on the slave 17512339Sjason@lowepower.com * port) and was unsuccesful. 17612339Sjason@lowepower.com */ 17712339Sjason@lowepower.com void recvReqRetry() override; 17812339Sjason@lowepower.com 17912339Sjason@lowepower.com /** 18012339Sjason@lowepower.com * Called to receive an address range change from the peer slave 18112339Sjason@lowepower.com * port. The default implementation ignores the change and does 18212339Sjason@lowepower.com * nothing. Override this function in a derived class if the owner 18312339Sjason@lowepower.com * needs to be aware of the address ranges, e.g. in an 18412339Sjason@lowepower.com * interconnect component like a bus. 18512339Sjason@lowepower.com */ 18612339Sjason@lowepower.com void recvRangeChange() override; 18712339Sjason@lowepower.com }; 18812339Sjason@lowepower.com 18912339Sjason@lowepower.com /** 19012339Sjason@lowepower.com * Handle the request from the CPU side. Called from the CPU port 19112339Sjason@lowepower.com * on a timing request. 19212339Sjason@lowepower.com * 19312339Sjason@lowepower.com * @param requesting packet 19412339Sjason@lowepower.com * @param id of the port to send the response 19512339Sjason@lowepower.com * @return true if we can handle the request this cycle, false if the 19612339Sjason@lowepower.com * requestor needs to retry later 19712339Sjason@lowepower.com */ 19812339Sjason@lowepower.com bool handleRequest(PacketPtr pkt, int port_id); 19912339Sjason@lowepower.com 20012339Sjason@lowepower.com /** 20112339Sjason@lowepower.com * Handle the respone from the memory side. Called from the memory port 20212339Sjason@lowepower.com * on a timing response. 20312339Sjason@lowepower.com * 20412339Sjason@lowepower.com * @param responding packet 20512339Sjason@lowepower.com * @return true if we can handle the response this cycle, false if the 20612339Sjason@lowepower.com * responder needs to retry later 20712339Sjason@lowepower.com */ 20812339Sjason@lowepower.com bool handleResponse(PacketPtr pkt); 20912339Sjason@lowepower.com 21012339Sjason@lowepower.com /** 21112339Sjason@lowepower.com * Send the packet to the CPU side. 21212339Sjason@lowepower.com * This function assumes the pkt is already a response packet and forwards 21312339Sjason@lowepower.com * it to the correct port. This function also unblocks this object and 21412339Sjason@lowepower.com * cleans up the whole request. 21512339Sjason@lowepower.com * 21612339Sjason@lowepower.com * @param the packet to send to the cpu side 21712339Sjason@lowepower.com */ 21812339Sjason@lowepower.com void sendResponse(PacketPtr pkt); 21912339Sjason@lowepower.com 22012339Sjason@lowepower.com /** 22112339Sjason@lowepower.com * Handle a packet functionally. Update the data on a write and get the 22212339Sjason@lowepower.com * data on a read. Called from CPU port on a recv functional. 22312339Sjason@lowepower.com * 22412339Sjason@lowepower.com * @param packet to functionally handle 22512339Sjason@lowepower.com */ 22612339Sjason@lowepower.com void handleFunctional(PacketPtr pkt); 22712339Sjason@lowepower.com 22812339Sjason@lowepower.com /** 22912339Sjason@lowepower.com * Access the cache for a timing access. This is called after the cache 23012339Sjason@lowepower.com * access latency has already elapsed. 23112339Sjason@lowepower.com */ 23212339Sjason@lowepower.com void accessTiming(PacketPtr pkt); 23312339Sjason@lowepower.com 23412339Sjason@lowepower.com /** 23512339Sjason@lowepower.com * This is where we actually update / read from the cache. This function 23612339Sjason@lowepower.com * is executed on both timing and functional accesses. 23712339Sjason@lowepower.com * 23812339Sjason@lowepower.com * @return true if a hit, false otherwise 23912339Sjason@lowepower.com */ 24012339Sjason@lowepower.com bool accessFunctional(PacketPtr pkt); 24112339Sjason@lowepower.com 24212339Sjason@lowepower.com /** 24312339Sjason@lowepower.com * Insert a block into the cache. If there is no room left in the cache, 24412339Sjason@lowepower.com * then this function evicts a random entry t make room for the new block. 24512339Sjason@lowepower.com * 24612339Sjason@lowepower.com * @param packet with the data (and address) to insert into the cache 24712339Sjason@lowepower.com */ 24812339Sjason@lowepower.com void insert(PacketPtr pkt); 24912339Sjason@lowepower.com 25012339Sjason@lowepower.com /** 25112339Sjason@lowepower.com * Return the address ranges this cache is responsible for. Just use the 25212339Sjason@lowepower.com * same as the next upper level of the hierarchy. 25312339Sjason@lowepower.com * 25412339Sjason@lowepower.com * @return the address ranges this cache is responsible for 25512339Sjason@lowepower.com */ 25612339Sjason@lowepower.com AddrRangeList getAddrRanges() const; 25712339Sjason@lowepower.com 25812339Sjason@lowepower.com /** 25912339Sjason@lowepower.com * Tell the CPU side to ask for our memory ranges. 26012339Sjason@lowepower.com */ 26112339Sjason@lowepower.com void sendRangeChange() const; 26212339Sjason@lowepower.com 26312339Sjason@lowepower.com /// Latency to check the cache. Number of cycles for both hit and miss 26412339Sjason@lowepower.com const Cycles latency; 26512339Sjason@lowepower.com 26612339Sjason@lowepower.com /// The block size for the cache 26712339Sjason@lowepower.com const unsigned blockSize; 26812339Sjason@lowepower.com 26912339Sjason@lowepower.com /// Number of blocks in the cache (size of cache / block size) 27012339Sjason@lowepower.com const unsigned capacity; 27112339Sjason@lowepower.com 27212339Sjason@lowepower.com /// Instantiation of the CPU-side port 27312339Sjason@lowepower.com std::vector<CPUSidePort> cpuPorts; 27412339Sjason@lowepower.com 27512339Sjason@lowepower.com /// Instantiation of the memory-side port 27612339Sjason@lowepower.com MemSidePort memPort; 27712339Sjason@lowepower.com 27812339Sjason@lowepower.com /// True if this cache is currently blocked waiting for a response. 27912339Sjason@lowepower.com bool blocked; 28012339Sjason@lowepower.com 28112339Sjason@lowepower.com /// Packet that we are currently handling. Used for upgrading to larger 28212339Sjason@lowepower.com /// cache line sizes 28312339Sjason@lowepower.com PacketPtr originalPacket; 28412339Sjason@lowepower.com 28512339Sjason@lowepower.com /// The port to send the response when we recieve it back 28612339Sjason@lowepower.com int waitingPortId; 28712339Sjason@lowepower.com 28812339Sjason@lowepower.com /// For tracking the miss latency 28912339Sjason@lowepower.com Tick missTime; 29012339Sjason@lowepower.com 29112339Sjason@lowepower.com /// An incredibly simple cache storage. Maps block addresses to data 29212339Sjason@lowepower.com std::unordered_map<Addr, uint8_t*> cacheStore; 29312339Sjason@lowepower.com 29412339Sjason@lowepower.com /// Cache statistics 29512339Sjason@lowepower.com Stats::Scalar hits; 29612339Sjason@lowepower.com Stats::Scalar misses; 29712339Sjason@lowepower.com Stats::Histogram missLatency; 29812339Sjason@lowepower.com Stats::Formula hitRatio; 29912339Sjason@lowepower.com 30012339Sjason@lowepower.com public: 30112339Sjason@lowepower.com 30212339Sjason@lowepower.com /** constructor 30312339Sjason@lowepower.com */ 30412339Sjason@lowepower.com SimpleCache(SimpleCacheParams *params); 30512339Sjason@lowepower.com 30612339Sjason@lowepower.com /** 30713784Sgabeblack@google.com * Get a port with a given name and index. This is used at 30812339Sjason@lowepower.com * binding time and returns a reference to a protocol-agnostic 30913784Sgabeblack@google.com * port. 31012339Sjason@lowepower.com * 31112339Sjason@lowepower.com * @param if_name Port name 31212339Sjason@lowepower.com * @param idx Index in the case of a VectorPort 31312339Sjason@lowepower.com * 31412339Sjason@lowepower.com * @return A reference to the given port 31512339Sjason@lowepower.com */ 31613784Sgabeblack@google.com Port &getPort(const std::string &if_name, 31713784Sgabeblack@google.com PortID idx=InvalidPortID) override; 31812339Sjason@lowepower.com 31912339Sjason@lowepower.com /** 32012339Sjason@lowepower.com * Register the stats 32112339Sjason@lowepower.com */ 32212339Sjason@lowepower.com void regStats() override; 32312339Sjason@lowepower.com}; 32412339Sjason@lowepower.com 32512339Sjason@lowepower.com 32612339Sjason@lowepower.com#endif // __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__ 327