simple_cache.hh revision 13784
1/* 2 * Copyright (c) 2017 Jason Lowe-Power 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Jason Lowe-Power 29 */ 30 31#ifndef __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__ 32#define __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__ 33 34#include <unordered_map> 35 36#include "mem/mem_object.hh" 37#include "params/SimpleCache.hh" 38 39/** 40 * A very simple cache object. Has a fully-associative data store with random 41 * replacement. 42 * This cache is fully blocking (not non-blocking). Only a single request can 43 * be outstanding at a time. 44 * This cache is a writeback cache. 45 */ 46class SimpleCache : public MemObject 47{ 48 private: 49 50 /** 51 * Port on the CPU-side that receives requests. 52 * Mostly just forwards requests to the cache (owner) 53 */ 54 class CPUSidePort : public SlavePort 55 { 56 private: 57 /// Since this is a vector port, need to know what number this one is 58 int id; 59 60 /// The object that owns this object (SimpleCache) 61 SimpleCache *owner; 62 63 /// True if the port needs to send a retry req. 64 bool needRetry; 65 66 /// If we tried to send a packet and it was blocked, store it here 67 PacketPtr blockedPacket; 68 69 public: 70 /** 71 * Constructor. Just calls the superclass constructor. 72 */ 73 CPUSidePort(const std::string& name, int id, SimpleCache *owner) : 74 SlavePort(name, owner), id(id), owner(owner), needRetry(false), 75 blockedPacket(nullptr) 76 { } 77 78 /** 79 * Send a packet across this port. This is called by the owner and 80 * all of the flow control is hanled in this function. 81 * This is a convenience function for the SimpleCache to send pkts. 82 * 83 * @param packet to send. 84 */ 85 void sendPacket(PacketPtr pkt); 86 87 /** 88 * Get a list of the non-overlapping address ranges the owner is 89 * responsible for. All slave ports must override this function 90 * and return a populated list with at least one item. 91 * 92 * @return a list of ranges responded to 93 */ 94 AddrRangeList getAddrRanges() const override; 95 96 /** 97 * Send a retry to the peer port only if it is needed. This is called 98 * from the SimpleCache whenever it is unblocked. 99 */ 100 void trySendRetry(); 101 102 protected: 103 /** 104 * Receive an atomic request packet from the master port. 105 * No need to implement in this simple cache. 106 */ 107 Tick recvAtomic(PacketPtr pkt) override 108 { panic("recvAtomic unimpl."); } 109 110 /** 111 * Receive a functional request packet from the master port. 112 * Performs a "debug" access updating/reading the data in place. 113 * 114 * @param packet the requestor sent. 115 */ 116 void recvFunctional(PacketPtr pkt) override; 117 118 /** 119 * Receive a timing request from the master port. 120 * 121 * @param the packet that the requestor sent 122 * @return whether this object can consume to packet. If false, we 123 * will call sendRetry() when we can try to receive this 124 * request again. 125 */ 126 bool recvTimingReq(PacketPtr pkt) override; 127 128 /** 129 * Called by the master port if sendTimingResp was called on this 130 * slave port (causing recvTimingResp to be called on the master 131 * port) and was unsuccesful. 132 */ 133 void recvRespRetry() override; 134 }; 135 136 /** 137 * Port on the memory-side that receives responses. 138 * Mostly just forwards requests to the cache (owner) 139 */ 140 class MemSidePort : public MasterPort 141 { 142 private: 143 /// The object that owns this object (SimpleCache) 144 SimpleCache *owner; 145 146 /// If we tried to send a packet and it was blocked, store it here 147 PacketPtr blockedPacket; 148 149 public: 150 /** 151 * Constructor. Just calls the superclass constructor. 152 */ 153 MemSidePort(const std::string& name, SimpleCache *owner) : 154 MasterPort(name, owner), owner(owner), blockedPacket(nullptr) 155 { } 156 157 /** 158 * Send a packet across this port. This is called by the owner and 159 * all of the flow control is hanled in this function. 160 * This is a convenience function for the SimpleCache to send pkts. 161 * 162 * @param packet to send. 163 */ 164 void sendPacket(PacketPtr pkt); 165 166 protected: 167 /** 168 * Receive a timing response from the slave port. 169 */ 170 bool recvTimingResp(PacketPtr pkt) override; 171 172 /** 173 * Called by the slave port if sendTimingReq was called on this 174 * master port (causing recvTimingReq to be called on the slave 175 * port) and was unsuccesful. 176 */ 177 void recvReqRetry() override; 178 179 /** 180 * Called to receive an address range change from the peer slave 181 * port. The default implementation ignores the change and does 182 * nothing. Override this function in a derived class if the owner 183 * needs to be aware of the address ranges, e.g. in an 184 * interconnect component like a bus. 185 */ 186 void recvRangeChange() override; 187 }; 188 189 /** 190 * Handle the request from the CPU side. Called from the CPU port 191 * on a timing request. 192 * 193 * @param requesting packet 194 * @param id of the port to send the response 195 * @return true if we can handle the request this cycle, false if the 196 * requestor needs to retry later 197 */ 198 bool handleRequest(PacketPtr pkt, int port_id); 199 200 /** 201 * Handle the respone from the memory side. Called from the memory port 202 * on a timing response. 203 * 204 * @param responding packet 205 * @return true if we can handle the response this cycle, false if the 206 * responder needs to retry later 207 */ 208 bool handleResponse(PacketPtr pkt); 209 210 /** 211 * Send the packet to the CPU side. 212 * This function assumes the pkt is already a response packet and forwards 213 * it to the correct port. This function also unblocks this object and 214 * cleans up the whole request. 215 * 216 * @param the packet to send to the cpu side 217 */ 218 void sendResponse(PacketPtr pkt); 219 220 /** 221 * Handle a packet functionally. Update the data on a write and get the 222 * data on a read. Called from CPU port on a recv functional. 223 * 224 * @param packet to functionally handle 225 */ 226 void handleFunctional(PacketPtr pkt); 227 228 /** 229 * Access the cache for a timing access. This is called after the cache 230 * access latency has already elapsed. 231 */ 232 void accessTiming(PacketPtr pkt); 233 234 /** 235 * This is where we actually update / read from the cache. This function 236 * is executed on both timing and functional accesses. 237 * 238 * @return true if a hit, false otherwise 239 */ 240 bool accessFunctional(PacketPtr pkt); 241 242 /** 243 * Insert a block into the cache. If there is no room left in the cache, 244 * then this function evicts a random entry t make room for the new block. 245 * 246 * @param packet with the data (and address) to insert into the cache 247 */ 248 void insert(PacketPtr pkt); 249 250 /** 251 * Return the address ranges this cache is responsible for. Just use the 252 * same as the next upper level of the hierarchy. 253 * 254 * @return the address ranges this cache is responsible for 255 */ 256 AddrRangeList getAddrRanges() const; 257 258 /** 259 * Tell the CPU side to ask for our memory ranges. 260 */ 261 void sendRangeChange() const; 262 263 /// Latency to check the cache. Number of cycles for both hit and miss 264 const Cycles latency; 265 266 /// The block size for the cache 267 const unsigned blockSize; 268 269 /// Number of blocks in the cache (size of cache / block size) 270 const unsigned capacity; 271 272 /// Instantiation of the CPU-side port 273 std::vector<CPUSidePort> cpuPorts; 274 275 /// Instantiation of the memory-side port 276 MemSidePort memPort; 277 278 /// True if this cache is currently blocked waiting for a response. 279 bool blocked; 280 281 /// Packet that we are currently handling. Used for upgrading to larger 282 /// cache line sizes 283 PacketPtr originalPacket; 284 285 /// The port to send the response when we recieve it back 286 int waitingPortId; 287 288 /// For tracking the miss latency 289 Tick missTime; 290 291 /// An incredibly simple cache storage. Maps block addresses to data 292 std::unordered_map<Addr, uint8_t*> cacheStore; 293 294 /// Cache statistics 295 Stats::Scalar hits; 296 Stats::Scalar misses; 297 Stats::Histogram missLatency; 298 Stats::Formula hitRatio; 299 300 public: 301 302 /** constructor 303 */ 304 SimpleCache(SimpleCacheParams *params); 305 306 /** 307 * Get a port with a given name and index. This is used at 308 * binding time and returns a reference to a protocol-agnostic 309 * port. 310 * 311 * @param if_name Port name 312 * @param idx Index in the case of a VectorPort 313 * 314 * @return A reference to the given port 315 */ 316 Port &getPort(const std::string &if_name, 317 PortID idx=InvalidPortID) override; 318 319 /** 320 * Register the stats 321 */ 322 void regStats() override; 323}; 324 325 326#endif // __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__ 327