1/*
2 * Copyright (c) 2018 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Author: Matteo Andreozzi
38 */
39
40
41#ifndef __MEM_QOS_MEM_SINK_HH__
42#define __MEM_QOS_MEM_SINK_HH__
43
44#include "mem/qos/mem_ctrl.hh"
45#include "mem/qport.hh"
46#include "params/QoSMemSinkCtrl.hh"
47
48namespace QoS {
49
50/**
51 * QoS Memory Sink
52 *
53 * The QoS Memory Sink is a lightweight memory controller with QoS
54 * support. It is meant to provide a QoS aware simple memory system
55 * without the need of using a complex DRAM memory controller
56 */
57class MemSinkCtrl : public MemCtrl
58{
59  protected:
60    /**
61     * The Request packets are store in a multiple dequeue structure,
62     * based on their QoS priority
63     */
64    using PacketQueue = std::deque<PacketPtr>;
65
66  private:
67    class MemoryPort : public QueuedSlavePort
68    {
69      private:
70        /** reference to parent memory object */
71        MemSinkCtrl& memory;
72
73        /** Outgoing packet responses queue */
74        RespPacketQueue queue;
75
76      public:
77       /**
78        * Constructor
79        *
80        * @param n port name
81        * @param m reference to ProfileGen parent object
82        */
83        MemoryPort(const std::string&, MemSinkCtrl&);
84
85      protected:
86       /**
87        * Receive a Packet in Atomic mode
88        *
89        * @param pkt pointer to memory packet
90        * @return packet access latency in ticks
91        */
92        Tick recvAtomic(PacketPtr pkt);
93
94        /**
95        * Receive a Packet in Functional mode
96        *
97        * @param pkt pointer to memory packet
98        */
99        void recvFunctional(PacketPtr pkt);
100
101        /**
102        * Receive a Packet in Timing mode
103        *
104        * @param pkt pointer to memory packet
105        * @return true if the request was accepted
106        */
107        bool recvTimingReq(PacketPtr pkt);
108
109        /**
110         * Gets the configured address ranges for this port
111         * @return the configured address ranges for this port
112         */
113        AddrRangeList getAddrRanges() const;
114
115    };
116
117  public:
118    /**
119     * QoS Memory Sink Constructor
120     *
121     * @param p QoS Memory Sink configuration parameters
122     */
123    MemSinkCtrl(const QoSMemSinkCtrlParams*);
124
125    virtual ~MemSinkCtrl();
126
127    /**
128     * Checks and return the Drain state of this SimObject
129     * @return current Drain state
130     */
131    DrainState drain() override;
132
133    /**
134     * Getter method to access this memory's slave port
135     *
136     * @param if_name interface name
137     * @param idx port ID number
138     * @return reference to this memory's slave port
139     */
140    Port &getPort(const std::string &if_name, PortID=InvalidPortID) override;
141
142    /**
143     * Initializes this object
144     */
145    void init() override;
146
147  protected:
148    /** Memory between requests latency (ticks) */
149    const Tick requestLatency;
150
151    /** Memory response latency (ticks) */
152    const Tick responseLatency;
153
154    /** Memory packet size in bytes */
155    const uint64_t memoryPacketSize;
156
157    /** Read request packets queue buffer size in #packets */
158    const uint64_t readBufferSize;
159
160    /** Write request packets queue buffer size in #packets */
161    const uint64_t writeBufferSize;
162
163    /** Memory slave port */
164    MemoryPort port;
165
166    /** Read request pending */
167    bool retryRdReq;
168
169    /** Write request pending */
170    bool retryWrReq;
171
172    /** Next request service time */
173    Tick nextRequest;
174
175    /** Count the number of read retries */
176    Stats::Scalar numReadRetries;
177
178    /** Count the number of write retries */
179    Stats::Scalar numWriteRetries;
180
181    /**
182     * QoS-aware (per priority) incoming read requests packets queue
183     */
184    std::vector<PacketQueue> readQueue;
185
186    /**
187     * QoS-aware (per priority) incoming read requests packets queue
188     */
189    std::vector<PacketQueue> writeQueue;
190
191    /**
192     * Processes the next Request event according to configured
193     * request latency
194     */
195    void processNextReqEvent();
196
197    /** Event wrapper to schedule next request handler function */
198    EventWrapper<
199        MemSinkCtrl,
200        &MemSinkCtrl::processNextReqEvent> nextReqEvent;
201
202    /**
203     * Check if the read queue has room for more entries
204     *
205     * @param packets The number of entries needed in the read queue
206     * @return true if read queue is full, false otherwise
207     */
208    inline bool readQueueFull(const uint64_t packets) const;
209
210    /**
211     * Check if the write queue has room for more entries
212     *
213     * @param packets  The number of entries needed in the write queue
214     * @return true if write queue is full, false otherwise
215     */
216    inline bool writeQueueFull(const uint64_t packets) const;
217
218    /**
219     * Receive a Packet in Atomic mode
220     *
221     * @param pkt pointer to memory packet
222     * @return packet access latency in ticks
223     */
224    Tick recvAtomic(PacketPtr pkt);
225
226    /**
227     * Receive a Packet in Functional mode
228     *
229     * @param pkt pointer to memory packet
230     */
231    void recvFunctional(PacketPtr pkt);
232
233   /**
234    * Receive a Packet in Timing mode
235    *
236    * @param pkt pointer to memory packet
237    * @return true if the request was accepted
238    */
239    bool recvTimingReq(PacketPtr pkt);
240
241    /** Registers statistics */
242    void regStats() override;
243};
244
245} // namespace QoS
246
247#endif /* __MEM_QOS_MEM_SINK_HH__ */
248