112338Sjason@lowepower.com/*
212338Sjason@lowepower.com * Copyright (c) 2017 Jason Lowe-Power
312338Sjason@lowepower.com * All rights reserved.
412338Sjason@lowepower.com *
512338Sjason@lowepower.com * Redistribution and use in source and binary forms, with or without
612338Sjason@lowepower.com * modification, are permitted provided that the following conditions are
712338Sjason@lowepower.com * met: redistributions of source code must retain the above copyright
812338Sjason@lowepower.com * notice, this list of conditions and the following disclaimer;
912338Sjason@lowepower.com * redistributions in binary form must reproduce the above copyright
1012338Sjason@lowepower.com * notice, this list of conditions and the following disclaimer in the
1112338Sjason@lowepower.com * documentation and/or other materials provided with the distribution;
1212338Sjason@lowepower.com * neither the name of the copyright holders nor the names of its
1312338Sjason@lowepower.com * contributors may be used to endorse or promote products derived from
1412338Sjason@lowepower.com * this software without specific prior written permission.
1512338Sjason@lowepower.com *
1612338Sjason@lowepower.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712338Sjason@lowepower.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812338Sjason@lowepower.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912338Sjason@lowepower.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012338Sjason@lowepower.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112338Sjason@lowepower.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212338Sjason@lowepower.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312338Sjason@lowepower.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412338Sjason@lowepower.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512338Sjason@lowepower.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612338Sjason@lowepower.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712338Sjason@lowepower.com *
2812338Sjason@lowepower.com * Authors: Jason Lowe-Power
2912338Sjason@lowepower.com */
3012338Sjason@lowepower.com
3112338Sjason@lowepower.com#ifndef __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
3212338Sjason@lowepower.com#define __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
3312338Sjason@lowepower.com
3414252Sgabeblack@google.com#include "mem/port.hh"
3512338Sjason@lowepower.com#include "params/SimpleMemobj.hh"
3614252Sgabeblack@google.com#include "sim/sim_object.hh"
3712338Sjason@lowepower.com
3812338Sjason@lowepower.com/**
3912338Sjason@lowepower.com * A very simple memory object. Current implementation doesn't even cache
4012338Sjason@lowepower.com * anything it just forwards requests and responses.
4112338Sjason@lowepower.com * This memobj is fully blocking (not non-blocking). Only a single request can
4212338Sjason@lowepower.com * be outstanding at a time.
4312338Sjason@lowepower.com */
4414252Sgabeblack@google.comclass SimpleMemobj : public SimObject
4512338Sjason@lowepower.com{
4612338Sjason@lowepower.com  private:
4712338Sjason@lowepower.com
4812338Sjason@lowepower.com    /**
4912338Sjason@lowepower.com     * Port on the CPU-side that receives requests.
5012338Sjason@lowepower.com     * Mostly just forwards requests to the owner.
5112338Sjason@lowepower.com     * Part of a vector of ports. One for each CPU port (e.g., data, inst)
5212338Sjason@lowepower.com     */
5312338Sjason@lowepower.com    class CPUSidePort : public SlavePort
5412338Sjason@lowepower.com    {
5512338Sjason@lowepower.com      private:
5612338Sjason@lowepower.com        /// The object that owns this object (SimpleMemobj)
5712338Sjason@lowepower.com        SimpleMemobj *owner;
5812338Sjason@lowepower.com
5912338Sjason@lowepower.com        /// True if the port needs to send a retry req.
6012338Sjason@lowepower.com        bool needRetry;
6112338Sjason@lowepower.com
6212338Sjason@lowepower.com        /// If we tried to send a packet and it was blocked, store it here
6312338Sjason@lowepower.com        PacketPtr blockedPacket;
6412338Sjason@lowepower.com
6512338Sjason@lowepower.com      public:
6612338Sjason@lowepower.com        /**
6712338Sjason@lowepower.com         * Constructor. Just calls the superclass constructor.
6812338Sjason@lowepower.com         */
6912338Sjason@lowepower.com        CPUSidePort(const std::string& name, SimpleMemobj *owner) :
7012338Sjason@lowepower.com            SlavePort(name, owner), owner(owner), needRetry(false),
7112338Sjason@lowepower.com            blockedPacket(nullptr)
7212338Sjason@lowepower.com        { }
7312338Sjason@lowepower.com
7412338Sjason@lowepower.com        /**
7512338Sjason@lowepower.com         * Send a packet across this port. This is called by the owner and
7612338Sjason@lowepower.com         * all of the flow control is hanled in this function.
7712338Sjason@lowepower.com         *
7812338Sjason@lowepower.com         * @param packet to send.
7912338Sjason@lowepower.com         */
8012338Sjason@lowepower.com        void sendPacket(PacketPtr pkt);
8112338Sjason@lowepower.com
8212338Sjason@lowepower.com        /**
8312338Sjason@lowepower.com         * Get a list of the non-overlapping address ranges the owner is
8412338Sjason@lowepower.com         * responsible for. All slave ports must override this function
8512338Sjason@lowepower.com         * and return a populated list with at least one item.
8612338Sjason@lowepower.com         *
8712338Sjason@lowepower.com         * @return a list of ranges responded to
8812338Sjason@lowepower.com         */
8912338Sjason@lowepower.com        AddrRangeList getAddrRanges() const override;
9012338Sjason@lowepower.com
9112338Sjason@lowepower.com        /**
9212338Sjason@lowepower.com         * Send a retry to the peer port only if it is needed. This is called
9312338Sjason@lowepower.com         * from the SimpleMemobj whenever it is unblocked.
9412338Sjason@lowepower.com         */
9512338Sjason@lowepower.com        void trySendRetry();
9612338Sjason@lowepower.com
9712338Sjason@lowepower.com      protected:
9812338Sjason@lowepower.com        /**
9912338Sjason@lowepower.com         * Receive an atomic request packet from the master port.
10012338Sjason@lowepower.com         * No need to implement in this simple memobj.
10112338Sjason@lowepower.com         */
10212338Sjason@lowepower.com        Tick recvAtomic(PacketPtr pkt) override
10312338Sjason@lowepower.com        { panic("recvAtomic unimpl."); }
10412338Sjason@lowepower.com
10512338Sjason@lowepower.com        /**
10612338Sjason@lowepower.com         * Receive a functional request packet from the master port.
10712338Sjason@lowepower.com         * Performs a "debug" access updating/reading the data in place.
10812338Sjason@lowepower.com         *
10912338Sjason@lowepower.com         * @param packet the requestor sent.
11012338Sjason@lowepower.com         */
11112338Sjason@lowepower.com        void recvFunctional(PacketPtr pkt) override;
11212338Sjason@lowepower.com
11312338Sjason@lowepower.com        /**
11412338Sjason@lowepower.com         * Receive a timing request from the master port.
11512338Sjason@lowepower.com         *
11612338Sjason@lowepower.com         * @param the packet that the requestor sent
11712338Sjason@lowepower.com         * @return whether this object can consume the packet. If false, we
11812338Sjason@lowepower.com         *         will call sendRetry() when we can try to receive this
11912338Sjason@lowepower.com         *         request again.
12012338Sjason@lowepower.com         */
12112338Sjason@lowepower.com        bool recvTimingReq(PacketPtr pkt) override;
12212338Sjason@lowepower.com
12312338Sjason@lowepower.com        /**
12412338Sjason@lowepower.com         * Called by the master port if sendTimingResp was called on this
12512338Sjason@lowepower.com         * slave port (causing recvTimingResp to be called on the master
12612338Sjason@lowepower.com         * port) and was unsuccesful.
12712338Sjason@lowepower.com         */
12812338Sjason@lowepower.com        void recvRespRetry() override;
12912338Sjason@lowepower.com    };
13012338Sjason@lowepower.com
13112338Sjason@lowepower.com    /**
13212338Sjason@lowepower.com     * Port on the memory-side that receives responses.
13312338Sjason@lowepower.com     * Mostly just forwards requests to the owner
13412338Sjason@lowepower.com     */
13512338Sjason@lowepower.com    class MemSidePort : public MasterPort
13612338Sjason@lowepower.com    {
13712338Sjason@lowepower.com      private:
13812338Sjason@lowepower.com        /// The object that owns this object (SimpleMemobj)
13912338Sjason@lowepower.com        SimpleMemobj *owner;
14012338Sjason@lowepower.com
14112338Sjason@lowepower.com        /// If we tried to send a packet and it was blocked, store it here
14212338Sjason@lowepower.com        PacketPtr blockedPacket;
14312338Sjason@lowepower.com
14412338Sjason@lowepower.com      public:
14512338Sjason@lowepower.com        /**
14612338Sjason@lowepower.com         * Constructor. Just calls the superclass constructor.
14712338Sjason@lowepower.com         */
14812338Sjason@lowepower.com        MemSidePort(const std::string& name, SimpleMemobj *owner) :
14912338Sjason@lowepower.com            MasterPort(name, owner), owner(owner), blockedPacket(nullptr)
15012338Sjason@lowepower.com        { }
15112338Sjason@lowepower.com
15212338Sjason@lowepower.com        /**
15312338Sjason@lowepower.com         * Send a packet across this port. This is called by the owner and
15412338Sjason@lowepower.com         * all of the flow control is hanled in this function.
15512338Sjason@lowepower.com         *
15612338Sjason@lowepower.com         * @param packet to send.
15712338Sjason@lowepower.com         */
15812338Sjason@lowepower.com        void sendPacket(PacketPtr pkt);
15912338Sjason@lowepower.com
16012338Sjason@lowepower.com      protected:
16112338Sjason@lowepower.com        /**
16212338Sjason@lowepower.com         * Receive a timing response from the slave port.
16312338Sjason@lowepower.com         */
16412338Sjason@lowepower.com        bool recvTimingResp(PacketPtr pkt) override;
16512338Sjason@lowepower.com
16612338Sjason@lowepower.com        /**
16712338Sjason@lowepower.com         * Called by the slave port if sendTimingReq was called on this
16812338Sjason@lowepower.com         * master port (causing recvTimingReq to be called on the slave
16912338Sjason@lowepower.com         * port) and was unsuccesful.
17012338Sjason@lowepower.com         */
17112338Sjason@lowepower.com        void recvReqRetry() override;
17212338Sjason@lowepower.com
17312338Sjason@lowepower.com        /**
17412338Sjason@lowepower.com         * Called to receive an address range change from the peer slave
17512338Sjason@lowepower.com         * port. The default implementation ignores the change and does
17612338Sjason@lowepower.com         * nothing. Override this function in a derived class if the owner
17712338Sjason@lowepower.com         * needs to be aware of the address ranges, e.g. in an
17812338Sjason@lowepower.com         * interconnect component like a bus.
17912338Sjason@lowepower.com         */
18012338Sjason@lowepower.com        void recvRangeChange() override;
18112338Sjason@lowepower.com    };
18212338Sjason@lowepower.com
18312338Sjason@lowepower.com    /**
18412338Sjason@lowepower.com     * Handle the request from the CPU side
18512338Sjason@lowepower.com     *
18612338Sjason@lowepower.com     * @param requesting packet
18712338Sjason@lowepower.com     * @return true if we can handle the request this cycle, false if the
18812338Sjason@lowepower.com     *         requestor needs to retry later
18912338Sjason@lowepower.com     */
19012338Sjason@lowepower.com    bool handleRequest(PacketPtr pkt);
19112338Sjason@lowepower.com
19212338Sjason@lowepower.com    /**
19312338Sjason@lowepower.com     * Handle the respone from the memory side
19412338Sjason@lowepower.com     *
19512338Sjason@lowepower.com     * @param responding packet
19612338Sjason@lowepower.com     * @return true if we can handle the response this cycle, false if the
19712338Sjason@lowepower.com     *         responder needs to retry later
19812338Sjason@lowepower.com     */
19912338Sjason@lowepower.com    bool handleResponse(PacketPtr pkt);
20012338Sjason@lowepower.com
20112338Sjason@lowepower.com    /**
20212338Sjason@lowepower.com     * Handle a packet functionally. Update the data on a write and get the
20312338Sjason@lowepower.com     * data on a read.
20412338Sjason@lowepower.com     *
20512338Sjason@lowepower.com     * @param packet to functionally handle
20612338Sjason@lowepower.com     */
20712338Sjason@lowepower.com    void handleFunctional(PacketPtr pkt);
20812338Sjason@lowepower.com
20912338Sjason@lowepower.com    /**
21012338Sjason@lowepower.com     * Return the address ranges this memobj is responsible for. Just use the
21112338Sjason@lowepower.com     * same as the next upper level of the hierarchy.
21212338Sjason@lowepower.com     *
21312338Sjason@lowepower.com     * @return the address ranges this memobj is responsible for
21412338Sjason@lowepower.com     */
21512338Sjason@lowepower.com    AddrRangeList getAddrRanges() const;
21612338Sjason@lowepower.com
21712338Sjason@lowepower.com    /**
21812338Sjason@lowepower.com     * Tell the CPU side to ask for our memory ranges.
21912338Sjason@lowepower.com     */
22012338Sjason@lowepower.com    void sendRangeChange();
22112338Sjason@lowepower.com
22212338Sjason@lowepower.com    /// Instantiation of the CPU-side ports
22312338Sjason@lowepower.com    CPUSidePort instPort;
22412338Sjason@lowepower.com    CPUSidePort dataPort;
22512338Sjason@lowepower.com
22612338Sjason@lowepower.com    /// Instantiation of the memory-side port
22712338Sjason@lowepower.com    MemSidePort memPort;
22812338Sjason@lowepower.com
22912338Sjason@lowepower.com    /// True if this is currently blocked waiting for a response.
23012338Sjason@lowepower.com    bool blocked;
23112338Sjason@lowepower.com
23212338Sjason@lowepower.com  public:
23312338Sjason@lowepower.com
23412338Sjason@lowepower.com    /** constructor
23512338Sjason@lowepower.com     */
23612338Sjason@lowepower.com    SimpleMemobj(SimpleMemobjParams *params);
23712338Sjason@lowepower.com
23812338Sjason@lowepower.com    /**
23913784Sgabeblack@google.com     * Get a port with a given name and index. This is used at
24012338Sjason@lowepower.com     * binding time and returns a reference to a protocol-agnostic
24113784Sgabeblack@google.com     * port.
24212338Sjason@lowepower.com     *
24312338Sjason@lowepower.com     * @param if_name Port name
24412338Sjason@lowepower.com     * @param idx Index in the case of a VectorPort
24512338Sjason@lowepower.com     *
24612338Sjason@lowepower.com     * @return A reference to the given port
24712338Sjason@lowepower.com     */
24813784Sgabeblack@google.com    Port &getPort(const std::string &if_name,
24913784Sgabeblack@google.com                  PortID idx=InvalidPortID) override;
25012338Sjason@lowepower.com};
25112338Sjason@lowepower.com
25212338Sjason@lowepower.com
25312338Sjason@lowepower.com#endif // __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
254