simple_memobj.hh revision 13784:1941dc118243
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_PART2_SIMPLE_MEMOBJ_HH__
32#define __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
33
34#include "mem/mem_object.hh"
35#include "params/SimpleMemobj.hh"
36
37/**
38 * A very simple memory object. Current implementation doesn't even cache
39 * anything it just forwards requests and responses.
40 * This memobj is fully blocking (not non-blocking). Only a single request can
41 * be outstanding at a time.
42 */
43class SimpleMemobj : public MemObject
44{
45  private:
46
47    /**
48     * Port on the CPU-side that receives requests.
49     * Mostly just forwards requests to the owner.
50     * Part of a vector of ports. One for each CPU port (e.g., data, inst)
51     */
52    class CPUSidePort : public SlavePort
53    {
54      private:
55        /// The object that owns this object (SimpleMemobj)
56        SimpleMemobj *owner;
57
58        /// True if the port needs to send a retry req.
59        bool needRetry;
60
61        /// If we tried to send a packet and it was blocked, store it here
62        PacketPtr blockedPacket;
63
64      public:
65        /**
66         * Constructor. Just calls the superclass constructor.
67         */
68        CPUSidePort(const std::string& name, SimpleMemobj *owner) :
69            SlavePort(name, owner), owner(owner), needRetry(false),
70            blockedPacket(nullptr)
71        { }
72
73        /**
74         * Send a packet across this port. This is called by the owner and
75         * all of the flow control is hanled in this function.
76         *
77         * @param packet to send.
78         */
79        void sendPacket(PacketPtr pkt);
80
81        /**
82         * Get a list of the non-overlapping address ranges the owner is
83         * responsible for. All slave ports must override this function
84         * and return a populated list with at least one item.
85         *
86         * @return a list of ranges responded to
87         */
88        AddrRangeList getAddrRanges() const override;
89
90        /**
91         * Send a retry to the peer port only if it is needed. This is called
92         * from the SimpleMemobj whenever it is unblocked.
93         */
94        void trySendRetry();
95
96      protected:
97        /**
98         * Receive an atomic request packet from the master port.
99         * No need to implement in this simple memobj.
100         */
101        Tick recvAtomic(PacketPtr pkt) override
102        { panic("recvAtomic unimpl."); }
103
104        /**
105         * Receive a functional request packet from the master port.
106         * Performs a "debug" access updating/reading the data in place.
107         *
108         * @param packet the requestor sent.
109         */
110        void recvFunctional(PacketPtr pkt) override;
111
112        /**
113         * Receive a timing request from the master port.
114         *
115         * @param the packet that the requestor sent
116         * @return whether this object can consume the packet. If false, we
117         *         will call sendRetry() when we can try to receive this
118         *         request again.
119         */
120        bool recvTimingReq(PacketPtr pkt) override;
121
122        /**
123         * Called by the master port if sendTimingResp was called on this
124         * slave port (causing recvTimingResp to be called on the master
125         * port) and was unsuccesful.
126         */
127        void recvRespRetry() override;
128    };
129
130    /**
131     * Port on the memory-side that receives responses.
132     * Mostly just forwards requests to the owner
133     */
134    class MemSidePort : public MasterPort
135    {
136      private:
137        /// The object that owns this object (SimpleMemobj)
138        SimpleMemobj *owner;
139
140        /// If we tried to send a packet and it was blocked, store it here
141        PacketPtr blockedPacket;
142
143      public:
144        /**
145         * Constructor. Just calls the superclass constructor.
146         */
147        MemSidePort(const std::string& name, SimpleMemobj *owner) :
148            MasterPort(name, owner), owner(owner), blockedPacket(nullptr)
149        { }
150
151        /**
152         * Send a packet across this port. This is called by the owner and
153         * all of the flow control is hanled in this function.
154         *
155         * @param packet to send.
156         */
157        void sendPacket(PacketPtr pkt);
158
159      protected:
160        /**
161         * Receive a timing response from the slave port.
162         */
163        bool recvTimingResp(PacketPtr pkt) override;
164
165        /**
166         * Called by the slave port if sendTimingReq was called on this
167         * master port (causing recvTimingReq to be called on the slave
168         * port) and was unsuccesful.
169         */
170        void recvReqRetry() override;
171
172        /**
173         * Called to receive an address range change from the peer slave
174         * port. The default implementation ignores the change and does
175         * nothing. Override this function in a derived class if the owner
176         * needs to be aware of the address ranges, e.g. in an
177         * interconnect component like a bus.
178         */
179        void recvRangeChange() override;
180    };
181
182    /**
183     * Handle the request from the CPU side
184     *
185     * @param requesting packet
186     * @return true if we can handle the request this cycle, false if the
187     *         requestor needs to retry later
188     */
189    bool handleRequest(PacketPtr pkt);
190
191    /**
192     * Handle the respone from the memory side
193     *
194     * @param responding packet
195     * @return true if we can handle the response this cycle, false if the
196     *         responder needs to retry later
197     */
198    bool handleResponse(PacketPtr pkt);
199
200    /**
201     * Handle a packet functionally. Update the data on a write and get the
202     * data on a read.
203     *
204     * @param packet to functionally handle
205     */
206    void handleFunctional(PacketPtr pkt);
207
208    /**
209     * Return the address ranges this memobj is responsible for. Just use the
210     * same as the next upper level of the hierarchy.
211     *
212     * @return the address ranges this memobj is responsible for
213     */
214    AddrRangeList getAddrRanges() const;
215
216    /**
217     * Tell the CPU side to ask for our memory ranges.
218     */
219    void sendRangeChange();
220
221    /// Instantiation of the CPU-side ports
222    CPUSidePort instPort;
223    CPUSidePort dataPort;
224
225    /// Instantiation of the memory-side port
226    MemSidePort memPort;
227
228    /// True if this is currently blocked waiting for a response.
229    bool blocked;
230
231  public:
232
233    /** constructor
234     */
235    SimpleMemobj(SimpleMemobjParams *params);
236
237    /**
238     * Get a port with a given name and index. This is used at
239     * binding time and returns a reference to a protocol-agnostic
240     * port.
241     *
242     * @param if_name Port name
243     * @param idx Index in the case of a VectorPort
244     *
245     * @return A reference to the given port
246     */
247    Port &getPort(const std::string &if_name,
248                  PortID idx=InvalidPortID) override;
249};
250
251
252#endif // __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
253