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