simple_cache.hh revision 12339
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    /**
30712339Sjason@lowepower.com     * Get a master port with a given name and index. This is used at
30812339Sjason@lowepower.com     * binding time and returns a reference to a protocol-agnostic
30912339Sjason@lowepower.com     * base master 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     */
31612339Sjason@lowepower.com    virtual BaseMasterPort& getMasterPort(const std::string& if_name,
31712339Sjason@lowepower.com                                          PortID idx = InvalidPortID) override;
31812339Sjason@lowepower.com
31912339Sjason@lowepower.com    /**
32012339Sjason@lowepower.com     * Get a slave port with a given name and index. This is used at
32112339Sjason@lowepower.com     * binding time and returns a reference to a protocol-agnostic
32212339Sjason@lowepower.com     * base master port.
32312339Sjason@lowepower.com     *
32412339Sjason@lowepower.com     * @param if_name Port name
32512339Sjason@lowepower.com     * @param idx Index in the case of a VectorPort
32612339Sjason@lowepower.com     *
32712339Sjason@lowepower.com     * @return A reference to the given port
32812339Sjason@lowepower.com     */
32912339Sjason@lowepower.com    virtual BaseSlavePort& getSlavePort(const std::string& if_name,
33012339Sjason@lowepower.com                                        PortID idx = InvalidPortID) override;
33112339Sjason@lowepower.com
33212339Sjason@lowepower.com    /**
33312339Sjason@lowepower.com     * Register the stats
33412339Sjason@lowepower.com     */
33512339Sjason@lowepower.com    void regStats() override;
33612339Sjason@lowepower.com};
33712339Sjason@lowepower.com
33812339Sjason@lowepower.com
33912339Sjason@lowepower.com#endif // __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__
340