gem5 v24.0.0.0
Loading...
Searching...
No Matches
mem_sink.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018-2020 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
38#include "mem/qos/mem_sink.hh"
39
40#include "base/logging.hh"
41#include "base/trace.hh"
42#include "debug/Drain.hh"
43#include "debug/QOS.hh"
44#include "mem/qos/q_policy.hh"
45#include "params/QoSMemSinkInterface.hh"
46
47namespace gem5
48{
49
50namespace memory
51{
52
53namespace qos
54{
55
56MemSinkCtrl::MemSinkCtrl(const QoSMemSinkCtrlParams &p)
57 : MemCtrl(p), requestLatency(p.request_latency),
58 responseLatency(p.response_latency),
59 memoryPacketSize(p.memory_packet_size),
60 readBufferSize(p.read_buffer_size),
61 writeBufferSize(p.write_buffer_size), port(name() + ".port", *this),
62 interface(p.interface),
63 retryRdReq(false), retryWrReq(false), nextRequest(0), nextReqEvent(*this),
64 stats(this)
65{
66 // Resize read and write queue to allocate space
67 // for configured QoS priorities
68 readQueue.resize(numPriorities());
69 writeQueue.resize(numPriorities());
70
71 interface->setMemCtrl(this);
72}
73
76
77void
79{
81
82 // Allow unconnected memories as this is used in several ruby
83 // systems at the moment
84 if (port.isConnected()) {
86 }
87}
88
89bool
90MemSinkCtrl::readQueueFull(const uint64_t packets) const
91{
92 return (totalReadQueueSize + packets > readBufferSize);
93}
94
95bool
96MemSinkCtrl::writeQueueFull(const uint64_t packets) const
97{
98 return (totalWriteQueueSize + packets > writeBufferSize);
99}
100
101Tick
103{
105 "%s Should not see packets where cache is responding\n",
106 __func__);
107
108 interface->access(pkt);
109 return responseLatency;
110}
111
112void
114{
115 pkt->pushLabel(name());
116
118
119 pkt->popLabel();
120}
121
122Port &
123MemSinkCtrl::getPort(const std::string &interface, PortID idx)
124{
125 if (interface != "port") {
126 return MemCtrl::getPort(interface, idx);
127 } else {
128 return port;
129 }
130}
131
132bool
134{
135 // Request accepted
136 bool req_accepted = true;
137
138 panic_if(!(pkt->isRead() || pkt->isWrite()),
139 "%s. Should only see "
140 "read and writes at memory controller\n",
141 __func__);
142
144 "%s. Should not see packets where cache is responding\n",
145 __func__);
146
147 DPRINTF(QOS,
148 "%s: REQUESTOR %s request %s addr %lld size %d\n",
149 __func__,
150 _system->getRequestorName(pkt->req->requestorId()),
151 pkt->cmdString(), pkt->getAddr(), pkt->getSize());
152
153 uint64_t required_entries = divCeil(pkt->getSize(), memoryPacketSize);
154
155 assert(required_entries);
156
157 // Schedule packet
158 uint8_t pkt_priority = qosSchedule({&readQueue, &writeQueue},
159 memoryPacketSize, pkt);
160
161 if (pkt->isRead()) {
162 if (readQueueFull(required_entries)) {
163 DPRINTF(QOS,
164 "%s Read queue full, not accepting\n", __func__);
165 // Remember that we have to retry this port
166 retryRdReq = true;
168 req_accepted = false;
169 } else {
170 // Enqueue the incoming packet into corresponding
171 // QoS priority queue
172 readQueue.at(pkt_priority).push_back(pkt);
173 queuePolicy->enqueuePacket(pkt);
174 }
175 } else {
176 if (writeQueueFull(required_entries)) {
177 DPRINTF(QOS,
178 "%s Write queue full, not accepting\n", __func__);
179 // Remember that we have to retry this port
180 retryWrReq = true;
182 req_accepted = false;
183 } else {
184 // Enqueue the incoming packet into corresponding QoS
185 // priority queue
186 writeQueue.at(pkt_priority).push_back(pkt);
187 queuePolicy->enqueuePacket(pkt);
188 }
189 }
190
191 if (req_accepted) {
192 // The packet is accepted - log it
193 logRequest(pkt->isRead()? READ : WRITE,
194 pkt->req->requestorId(),
195 pkt->qosValue(),
196 pkt->getAddr(),
197 required_entries);
198 }
199
200 // Check if we have to process next request event
201 if (!nextReqEvent.scheduled()) {
202 DPRINTF(QOS,
203 "%s scheduling next request at "
204 "time %d (next is %d)\n", __func__,
205 std::max(curTick(), nextRequest), nextRequest);
207 }
208 return req_accepted;
209}
210
211void
213{
214 PacketPtr pkt = nullptr;
215
216 // Evaluate bus direction
218
219 // Record turnaround stats and update current state direction
221
222 // Set current bus state
224
225 // Access current direction buffer
226 std::vector<PacketQueue>* queue_ptr = (busState == READ ? &readQueue :
227 &writeQueue);
228
229 DPRINTF(QOS,
230 "%s DUMPING %s queues status\n", __func__,
231 (busState == WRITE ? "WRITE" : "READ"));
232
233 if (debug::QOS) {
234 for (uint8_t i = 0; i < numPriorities(); ++i) {
235 std::string plist = "";
236 for (auto& e : (busState == WRITE ? writeQueue[i]: readQueue[i])) {
237 plist += (std::to_string(e->req->requestorId())) + " ";
238 }
239 DPRINTF(QOS,
240 "%s priority Queue [%i] contains %i elements, "
241 "packets are: [%s]\n", __func__, i,
244 plist);
245 }
246 }
247
248 uint8_t curr_prio = numPriorities();
249
250 for (auto queue = (*queue_ptr).rbegin();
251 queue != (*queue_ptr).rend(); ++queue) {
252
253 curr_prio--;
254
255 DPRINTF(QOS,
256 "%s checking %s queue [%d] priority [%d packets]\n",
257 __func__, (busState == READ? "READ" : "WRITE"),
258 curr_prio, queue->size());
259
260 if (!queue->empty()) {
261 // Call the queue policy to select packet from priority queue
262 auto p_it = queuePolicy->selectPacket(&(*queue));
263 pkt = *p_it;
264 queue->erase(p_it);
265
266 DPRINTF(QOS,
267 "%s scheduling packet address %d for requestor %s from "
268 "priority queue %d\n", __func__, pkt->getAddr(),
269 _system->getRequestorName(pkt->req->requestorId()),
270 curr_prio);
271 break;
272 }
273 }
274
275 assert(pkt);
276
277 // Setup next request service time - do it here as retry request
278 // hands over control to the port
280
281 uint64_t removed_entries = divCeil(pkt->getSize(), memoryPacketSize);
282
283 DPRINTF(QOS,
284 "%s scheduled packet address %d for requestor %s size is %d, "
285 "corresponds to %d memory packets\n", __func__, pkt->getAddr(),
286 _system->getRequestorName(pkt->req->requestorId()),
287 pkt->getSize(), removed_entries);
288
289 // Schedule response
290 panic_if(!pkt->needsResponse(),
291 "%s response not required\n", __func__);
292
293 // Do the actual memory access which also turns the packet
294 // into a response
295 interface->access(pkt);
296
297 // Log the response
298 logResponse(pkt->isRead()? READ : WRITE,
299 pkt->req->requestorId(),
300 pkt->qosValue(),
301 pkt->getAddr(),
302 removed_entries, responseLatency);
303
304 // Schedule the response
306 DPRINTF(QOS,
307 "%s response scheduled at time %d\n",
308 __func__, curTick() + responseLatency);
309
310 // Finally - handle retry requests - this handles control
311 // to the port, so do it last
312 if (busState == READ && retryRdReq) {
313 retryRdReq = false;
315 } else if (busState == WRITE && retryWrReq) {
316 retryWrReq = false;
318 }
319
320 // Check if we have to schedule another request event
323
325 DPRINTF(QOS,
326 "%s scheduling next request event at tick %d\n",
327 __func__, curTick() + requestLatency);
328 }
329}
330
333{
335 DPRINTF(Drain,
336 "%s queues have requests, waiting to drain\n",
337 __func__);
339 } else {
340 return DrainState::Drained;
341 }
342}
343
345 : statistics::Group(parent),
346 ADD_STAT(numReadRetries, statistics::units::Count::get(),
347 "Number of read retries"),
348 ADD_STAT(numWriteRetries, statistics::units::Count::get(),
349 "Number of write retries")
350{
351}
352
354 MemSinkCtrl& m)
355 : QueuedResponsePort(n, queue, true),
356 mem(m), queue(mem, *this, true)
357{}
358
361{
362 AddrRangeList ranges;
363 ranges.push_back(mem.interface->getAddrRange());
364 return ranges;
365}
366
367Tick
369{
370 return mem.recvAtomic(pkt);
371}
372
373void
375{
376 pkt->pushLabel(mem.name());
377
378 if (!queue.trySatisfyFunctional(pkt)) {
379 // Default implementation of SimpleTimingPort::recvFunctional()
380 // calls recvAtomic() and throws away the latency; we can save a
381 // little here by just not calculating the latency.
382 mem.recvFunctional(pkt);
383 }
384
385 pkt->popLabel();
386}
387
388bool
390{
391 return mem.recvTimingReq(pkt);
392}
393
394MemSinkInterface::MemSinkInterface(const QoSMemSinkInterfaceParams &_p)
395 : AbstractMemory(_p)
396{
397}
398
399} // namespace qos
400} // namespace memory
401} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
virtual std::string name() const
Definition named.hh:47
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
bool isRead() const
Definition packet.hh:593
Addr getAddr() const
Definition packet.hh:807
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
Definition packet.hh:1470
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition packet.hh:588
bool needsResponse() const
Definition packet.hh:608
uint8_t qosValue() const
QoS Value getter Returns 0 if QoS value was never set (constructor default).
Definition packet.hh:769
bool isWrite() const
Definition packet.hh:594
RequestPtr req
A pointer to the original request.
Definition packet.hh:377
unsigned getSize() const
Definition packet.hh:817
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition packet.hh:1480
bool cacheResponding() const
Definition packet.hh:659
Ports are used to interface objects to each other.
Definition port.hh:62
bool isConnected() const
Is this port currently connected to a peer?
Definition port.hh:133
A queued port is a port that has an infinite queue for outgoing packets and thus decouples the module...
Definition qport.hh:62
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
Definition qport.hh:94
void sendRangeChange() const
Called by the owner to send a range change.
Definition port.hh:380
void sendRetryReq()
Send a retry to the request port that previously attempted a sendTimingReq to this response port and ...
Definition port.hh:489
std::string getRequestorName(RequestorID requestor_id)
Get the name of an object for a given request id.
Definition system.cc:526
An abstract memory represents a contiguous block of physical memory, with an associated address range...
void access(PacketPtr pkt)
Perform an untimed memory access and update all the state (e.g.
void functionalAccess(PacketPtr pkt)
Perform an untimed memory read or write without changing anything but the memory itself.
The qos::MemCtrl is a base class for Memory objects which support QoS - it provides access to a set o...
Definition mem_ctrl.hh:80
void logResponse(BusState dir, RequestorID id, uint8_t _qos, Addr addr, uint64_t entries, double delay)
Called upon receiving a response, updates statistics and updates queues status.
Definition mem_ctrl.cc:148
std::vector< uint64_t > writeQueueSizes
Write request packets queue length in #packets, per QoS priority.
Definition mem_ctrl.hh:127
uint8_t qosSchedule(std::initializer_list< Queues * > queues_ptr, uint64_t queue_entry_size, const PacketPtr pkt)
Assign priority to a packet by executing the configured QoS policy.
Definition mem_ctrl.hh:495
uint64_t totalWriteQueueSize
Total write request packets queue length in #packets.
Definition mem_ctrl.hh:133
void recordTurnaroundStats(BusState busState, BusState busStateNext)
Record statistics on turnarounds based on busStateNext and busState values.
Definition mem_ctrl.cc:358
void setCurrentBusState()
Set current bus direction (READ or WRITE) from next selected one.
Definition mem_ctrl.hh:239
std::vector< uint64_t > readQueueSizes
Read request packets queue length in #packets, per QoS priority.
Definition mem_ctrl.hh:124
const std::unique_ptr< QueuePolicy > queuePolicy
QoS Queue Policy: selects packet among same-priority queue.
Definition mem_ctrl.hh:93
BusState selectNextBusState()
Returns next bus direction (READ or WRITE) based on configured policy.
Definition mem_ctrl.cc:246
uint8_t numPriorities() const
Gets the total number of priority levels in the QoS memory controller.
Definition mem_ctrl.hh:366
BusState busState
Bus state used to control the read/write switching and drive the scheduling of the next request.
Definition mem_ctrl.hh:139
System * _system
Pointer to the System object.
Definition mem_ctrl.hh:175
uint64_t totalReadQueueSize
Total read request packets queue length in #packets.
Definition mem_ctrl.hh:130
BusState busStateNext
bus state for next request event triggered
Definition mem_ctrl.hh:142
uint8_t schedule(RequestorID id, uint64_t data)
Definition mem_ctrl.cc:217
void logRequest(BusState dir, RequestorID id, uint8_t _qos, Addr addr, uint64_t entries)
Called upon receiving a request or updates statistics and updates queues status.
Definition mem_ctrl.cc:91
void recvFunctional(PacketPtr pkt)
Receive a Packet in Functional mode.
Definition mem_sink.cc:374
MemoryPort(const std::string &, MemSinkCtrl &)
Constructor.
Definition mem_sink.cc:353
AddrRangeList getAddrRanges() const
Gets the configured address ranges for this port.
Definition mem_sink.cc:360
Tick recvAtomic(PacketPtr pkt)
Receive a Packet in Atomic mode.
Definition mem_sink.cc:368
bool recvTimingReq(PacketPtr pkt)
Receive a Packet in Timing mode.
Definition mem_sink.cc:389
MemoryPort port
Memory response port.
Definition mem_sink.hh:181
Tick recvAtomic(PacketPtr pkt)
Receive a Packet in Atomic mode.
Definition mem_sink.cc:102
const Tick responseLatency
Memory response latency (ticks)
Definition mem_sink.hh:169
Port & getPort(const std::string &if_name, PortID=InvalidPortID) override
Getter method to access this memory's response port.
Definition mem_sink.cc:123
MemberEventWrapper<&MemSinkCtrl::processNextReqEvent > nextReqEvent
Event wrapper to schedule next request handler function.
Definition mem_sink.hh:225
const uint64_t writeBufferSize
Write request packets queue buffer size in #packets.
Definition mem_sink.hh:178
DrainState drain() override
Checks and return the Drain state of this SimObject.
Definition mem_sink.cc:332
bool readQueueFull(const uint64_t packets) const
Check if the read queue has room for more entries.
Definition mem_sink.cc:90
bool recvTimingReq(PacketPtr pkt)
Receive a Packet in Timing mode.
Definition mem_sink.cc:133
const uint64_t readBufferSize
Read request packets queue buffer size in #packets.
Definition mem_sink.hh:175
bool retryWrReq
Write request pending.
Definition mem_sink.hh:192
std::vector< PacketQueue > readQueue
QoS-aware (per priority) incoming read requests packets queue.
Definition mem_sink.hh:211
bool retryRdReq
Read request pending.
Definition mem_sink.hh:189
void processNextReqEvent()
Processes the next Request event according to configured request latency.
Definition mem_sink.cc:212
bool writeQueueFull(const uint64_t packets) const
Check if the write queue has room for more entries.
Definition mem_sink.cc:96
const Tick requestLatency
Memory between requests latency (ticks)
Definition mem_sink.hh:166
const uint64_t memoryPacketSize
Memory packet size in bytes.
Definition mem_sink.hh:172
void init() override
Initializes this object.
Definition mem_sink.cc:78
MemSinkCtrl(const QoSMemSinkCtrlParams &)
QoS Memory Sink Constructor.
Definition mem_sink.cc:56
void recvFunctional(PacketPtr pkt)
Receive a Packet in Functional mode.
Definition mem_sink.cc:113
Tick nextRequest
Next request service time.
Definition mem_sink.hh:195
std::vector< PacketQueue > writeQueue
QoS-aware (per priority) incoming read requests packets queue.
Definition mem_sink.hh:216
MemSinkInterface *const interface
Create pointer to interface of actual media.
Definition mem_sink.hh:186
MemSinkInterface(const QoSMemSinkInterfaceParams &_p)
Definition mem_sink.cc:394
void setMemCtrl(MemSinkCtrl *_ctrl)
Setting a pointer to the interface.
Definition mem_sink.hh:273
Statistics container.
Definition group.hh:93
STL vector class.
Definition stl.hh:37
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
static constexpr T divCeil(const T &a, const U &b)
Definition intmath.hh:110
DrainState
Object drain/handover states.
Definition drain.hh:75
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
bool scheduled() const
Determine if the current event is scheduled.
Definition eventq.hh:458
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:214
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition sim_object.cc:73
Bitfield< 31 > n
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 9 > e
Definition misc_types.hh:65
Bitfield< 0 > m
Bitfield< 0 > p
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition types.hh:245
uint64_t Tick
Tick count type.
Definition types.hh:58
statistics::Scalar numReadRetries
Count the number of read retries.
Definition mem_sink.hh:202
MemSinkCtrlStats(statistics::Group *parent)
Definition mem_sink.cc:344
statistics::Scalar numWriteRetries
Count the number of write retries.
Definition mem_sink.hh:205
Definition mem.h:38
bool_vector8 mem[]
Definition reset_stim.h:43
const std::string & name()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:05 for gem5 by doxygen 1.11.0