From 43a1ea88b89aa3611d3b73cc0d4dc5de3f1f5e6b Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Fri, 6 Oct 2017 14:54:02 -0700 Subject: learning_gem5: Adding code for SimpleCache This is the rest of the code for part 2. See http://learning.gem5.org/book/part2/simplecache.html Change-Id: I5db099266a1196914656be3858fdd5fb4f8eab48 Signed-off-by: Jason Lowe-Power Reviewed-on: https://gem5-review.googlesource.com/5023 Reviewed-by: Nikos Nikoleris --- src/learning_gem5/part2/simple_cache.hh | 339 ++++++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 src/learning_gem5/part2/simple_cache.hh (limited to 'src/learning_gem5/part2/simple_cache.hh') diff --git a/src/learning_gem5/part2/simple_cache.hh b/src/learning_gem5/part2/simple_cache.hh new file mode 100644 index 000000000..7d53ffed0 --- /dev/null +++ b/src/learning_gem5/part2/simple_cache.hh @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2017 Jason Lowe-Power + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Jason Lowe-Power + */ + +#ifndef __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__ +#define __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__ + +#include + +#include "mem/mem_object.hh" +#include "params/SimpleCache.hh" + +/** + * A very simple cache object. Has a fully-associative data store with random + * replacement. + * This cache is fully blocking (not non-blocking). Only a single request can + * be outstanding at a time. + * This cache is a writeback cache. + */ +class SimpleCache : public MemObject +{ + private: + + /** + * Port on the CPU-side that receives requests. + * Mostly just forwards requests to the cache (owner) + */ + class CPUSidePort : public SlavePort + { + private: + /// Since this is a vector port, need to know what number this one is + int id; + + /// The object that owns this object (SimpleCache) + SimpleCache *owner; + + /// True if the port needs to send a retry req. + bool needRetry; + + /// If we tried to send a packet and it was blocked, store it here + PacketPtr blockedPacket; + + public: + /** + * Constructor. Just calls the superclass constructor. + */ + CPUSidePort(const std::string& name, int id, SimpleCache *owner) : + SlavePort(name, owner), id(id), owner(owner), needRetry(false), + blockedPacket(nullptr) + { } + + /** + * Send a packet across this port. This is called by the owner and + * all of the flow control is hanled in this function. + * This is a convenience function for the SimpleCache to send pkts. + * + * @param packet to send. + */ + void sendPacket(PacketPtr pkt); + + /** + * Get a list of the non-overlapping address ranges the owner is + * responsible for. All slave ports must override this function + * and return a populated list with at least one item. + * + * @return a list of ranges responded to + */ + AddrRangeList getAddrRanges() const override; + + /** + * Send a retry to the peer port only if it is needed. This is called + * from the SimpleCache whenever it is unblocked. + */ + void trySendRetry(); + + protected: + /** + * Receive an atomic request packet from the master port. + * No need to implement in this simple cache. + */ + Tick recvAtomic(PacketPtr pkt) override + { panic("recvAtomic unimpl."); } + + /** + * Receive a functional request packet from the master port. + * Performs a "debug" access updating/reading the data in place. + * + * @param packet the requestor sent. + */ + void recvFunctional(PacketPtr pkt) override; + + /** + * Receive a timing request from the master port. + * + * @param the packet that the requestor sent + * @return whether this object can consume to packet. If false, we + * will call sendRetry() when we can try to receive this + * request again. + */ + bool recvTimingReq(PacketPtr pkt) override; + + /** + * Called by the master port if sendTimingResp was called on this + * slave port (causing recvTimingResp to be called on the master + * port) and was unsuccesful. + */ + void recvRespRetry() override; + }; + + /** + * Port on the memory-side that receives responses. + * Mostly just forwards requests to the cache (owner) + */ + class MemSidePort : public MasterPort + { + private: + /// The object that owns this object (SimpleCache) + SimpleCache *owner; + + /// If we tried to send a packet and it was blocked, store it here + PacketPtr blockedPacket; + + public: + /** + * Constructor. Just calls the superclass constructor. + */ + MemSidePort(const std::string& name, SimpleCache *owner) : + MasterPort(name, owner), owner(owner), blockedPacket(nullptr) + { } + + /** + * Send a packet across this port. This is called by the owner and + * all of the flow control is hanled in this function. + * This is a convenience function for the SimpleCache to send pkts. + * + * @param packet to send. + */ + void sendPacket(PacketPtr pkt); + + protected: + /** + * Receive a timing response from the slave port. + */ + bool recvTimingResp(PacketPtr pkt) override; + + /** + * Called by the slave port if sendTimingReq was called on this + * master port (causing recvTimingReq to be called on the slave + * port) and was unsuccesful. + */ + void recvReqRetry() override; + + /** + * Called to receive an address range change from the peer slave + * port. The default implementation ignores the change and does + * nothing. Override this function in a derived class if the owner + * needs to be aware of the address ranges, e.g. in an + * interconnect component like a bus. + */ + void recvRangeChange() override; + }; + + /** + * Handle the request from the CPU side. Called from the CPU port + * on a timing request. + * + * @param requesting packet + * @param id of the port to send the response + * @return true if we can handle the request this cycle, false if the + * requestor needs to retry later + */ + bool handleRequest(PacketPtr pkt, int port_id); + + /** + * Handle the respone from the memory side. Called from the memory port + * on a timing response. + * + * @param responding packet + * @return true if we can handle the response this cycle, false if the + * responder needs to retry later + */ + bool handleResponse(PacketPtr pkt); + + /** + * Send the packet to the CPU side. + * This function assumes the pkt is already a response packet and forwards + * it to the correct port. This function also unblocks this object and + * cleans up the whole request. + * + * @param the packet to send to the cpu side + */ + void sendResponse(PacketPtr pkt); + + /** + * Handle a packet functionally. Update the data on a write and get the + * data on a read. Called from CPU port on a recv functional. + * + * @param packet to functionally handle + */ + void handleFunctional(PacketPtr pkt); + + /** + * Access the cache for a timing access. This is called after the cache + * access latency has already elapsed. + */ + void accessTiming(PacketPtr pkt); + + /** + * This is where we actually update / read from the cache. This function + * is executed on both timing and functional accesses. + * + * @return true if a hit, false otherwise + */ + bool accessFunctional(PacketPtr pkt); + + /** + * Insert a block into the cache. If there is no room left in the cache, + * then this function evicts a random entry t make room for the new block. + * + * @param packet with the data (and address) to insert into the cache + */ + void insert(PacketPtr pkt); + + /** + * Return the address ranges this cache is responsible for. Just use the + * same as the next upper level of the hierarchy. + * + * @return the address ranges this cache is responsible for + */ + AddrRangeList getAddrRanges() const; + + /** + * Tell the CPU side to ask for our memory ranges. + */ + void sendRangeChange() const; + + /// Latency to check the cache. Number of cycles for both hit and miss + const Cycles latency; + + /// The block size for the cache + const unsigned blockSize; + + /// Number of blocks in the cache (size of cache / block size) + const unsigned capacity; + + /// Instantiation of the CPU-side port + std::vector cpuPorts; + + /// Instantiation of the memory-side port + MemSidePort memPort; + + /// True if this cache is currently blocked waiting for a response. + bool blocked; + + /// Packet that we are currently handling. Used for upgrading to larger + /// cache line sizes + PacketPtr originalPacket; + + /// The port to send the response when we recieve it back + int waitingPortId; + + /// For tracking the miss latency + Tick missTime; + + /// An incredibly simple cache storage. Maps block addresses to data + std::unordered_map cacheStore; + + /// Cache statistics + Stats::Scalar hits; + Stats::Scalar misses; + Stats::Histogram missLatency; + Stats::Formula hitRatio; + + public: + + /** constructor + */ + SimpleCache(SimpleCacheParams *params); + + /** + * Get a master port with a given name and index. This is used at + * binding time and returns a reference to a protocol-agnostic + * base master port. + * + * @param if_name Port name + * @param idx Index in the case of a VectorPort + * + * @return A reference to the given port + */ + virtual BaseMasterPort& getMasterPort(const std::string& if_name, + PortID idx = InvalidPortID) override; + + /** + * Get a slave port with a given name and index. This is used at + * binding time and returns a reference to a protocol-agnostic + * base master port. + * + * @param if_name Port name + * @param idx Index in the case of a VectorPort + * + * @return A reference to the given port + */ + virtual BaseSlavePort& getSlavePort(const std::string& if_name, + PortID idx = InvalidPortID) override; + + /** + * Register the stats + */ + void regStats() override; +}; + + +#endif // __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__ -- cgit v1.2.3