gem5 v24.0.0.0
Loading...
Searching...
No Matches
mem_ctrl.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017-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_ctrl.hh"
39
40#include "mem/qos/policy.hh"
41#include "mem/qos/q_policy.hh"
43#include "sim/core.hh"
44
45namespace gem5
46{
47
48namespace memory
49{
50
51namespace qos
52{
53
54MemCtrl::MemCtrl(const QoSMemCtrlParams &p)
56 policy(p.qos_policy),
57 turnPolicy(p.qos_turnaround_policy),
58 queuePolicy(QueuePolicy::create(p)),
59 _numPriorities(p.qos_priorities),
60 qosPriorityEscalation(p.qos_priority_escalation),
61 qosSyncroScheduler(p.qos_syncro_scheduler),
62 totalReadQueueSize(0), totalWriteQueueSize(0),
63 busState(READ), busStateNext(READ),
64 stats(*this),
65 _system(p.system)
66{
67 // Set the priority policy
68 if (policy) {
69 policy->setMemCtrl(this);
70 }
71
72 // Set the queue priority policy
73 if (queuePolicy) {
74 queuePolicy->setMemCtrl(this);
75 }
76
77 // Set the bus turnaround policy
78 if (turnPolicy) {
79 turnPolicy->setMemCtrl(this);
80 }
81
85}
86
89
90void
92 Addr addr, uint64_t entries)
93{
94 // If needed, initialize all counters and statistics
95 // for this requestor
96 addRequestor(id);
97
98 DPRINTF(QOS,
99 "qos::MemCtrl::logRequest REQUESTOR %s [id %d] address %#x"
100 " prio %d this requestor q packets %d"
101 " - queue size %d - requested entries %d\n",
102 requestors[id], id, addr, _qos, packetPriorities[id][_qos],
103 (dir == READ) ? readQueueSizes[_qos]: writeQueueSizes[_qos],
104 entries);
105
106 if (dir == READ) {
107 readQueueSizes[_qos] += entries;
108 totalReadQueueSize += entries;
109 } else if (dir == WRITE) {
110 writeQueueSizes[_qos] += entries;
111 totalWriteQueueSize += entries;
112 }
113
114 packetPriorities[id][_qos] += entries;
115 for (auto j = 0; j < entries; ++j) {
116 requestTimes[id][addr].push_back(curTick());
117 }
118
119 // Record statistics
120 stats.avgPriority[id].sample(_qos);
121
122 // Compute avg priority distance
123
124 for (uint8_t i = 0; i < packetPriorities[id].size(); ++i) {
125 uint8_t distance =
126 (abs(int(_qos) - int(i))) * packetPriorities[id][i];
127
128 if (distance > 0) {
129 stats.avgPriorityDistance[id].sample(distance);
130 DPRINTF(QOS,
131 "qos::MemCtrl::logRequest REQUESTOR %s [id %d]"
132 " registering priority distance %d for priority %d"
133 " (packets %d)\n",
134 requestors[id], id, distance, i,
135 packetPriorities[id][i]);
136 }
137 }
138
139 DPRINTF(QOS,
140 "qos::MemCtrl::logRequest REQUESTOR %s [id %d] prio %d "
141 "this requestor q packets %d - new queue size %d\n",
142 requestors[id], id, _qos, packetPriorities[id][_qos],
143 (dir == READ) ? readQueueSizes[_qos]: writeQueueSizes[_qos]);
144
145}
146
147void
149 Addr addr, uint64_t entries, double delay)
150{
152 "Logging response with invalid requestor\n");
153
154 DPRINTF(QOS,
155 "qos::MemCtrl::logResponse REQUESTOR %s [id %d] address %#x prio"
156 " %d this requestor q packets %d"
157 " - queue size %d - requested entries %d\n",
158 requestors[id], id, addr, _qos, packetPriorities[id][_qos],
159 (dir == READ) ? readQueueSizes[_qos]: writeQueueSizes[_qos],
160 entries);
161
162 if (dir == READ) {
163 readQueueSizes[_qos] -= entries;
164 totalReadQueueSize -= entries;
165 } else if (dir == WRITE) {
166 writeQueueSizes[_qos] -= entries;
167 totalWriteQueueSize -= entries;
168 }
169
170 panic_if(packetPriorities[id][_qos] == 0,
171 "qos::MemCtrl::logResponse requestor %s negative packets "
172 "for priority %d", requestors[id], _qos);
173
174 packetPriorities[id][_qos] -= entries;
175
176 for (auto j = 0; j < entries; ++j) {
177 auto it = requestTimes[id].find(addr);
178 panic_if(it == requestTimes[id].end(),
179 "qos::MemCtrl::logResponse requestor %s unmatched response "
180 "for address %#x received", requestors[id], addr);
181
182 // Load request time
183 uint64_t requestTime = it->second.front();
184
185 // Remove request entry
186 it->second.pop_front();
187
188 // Remove whole address entry if last one
189 if (it->second.empty()) {
190 requestTimes[id].erase(it);
191 }
192 // Compute latency
193 double latency = (double) (curTick() + delay - requestTime)
195
196 if (latency > 0) {
197 // Record per-priority latency stats
198 if (stats.priorityMaxLatency[_qos].value() < latency) {
199 stats.priorityMaxLatency[_qos] = latency;
200 }
201
202 if (stats.priorityMinLatency[_qos].value() > latency
203 || stats.priorityMinLatency[_qos].value() == 0) {
204 stats.priorityMinLatency[_qos] = latency;
205 }
206 }
207 }
208
209 DPRINTF(QOS,
210 "qos::MemCtrl::logResponse REQUESTOR %s [id %d] prio %d "
211 "this requestor q packets %d - new queue size %d\n",
212 requestors[id], id, _qos, packetPriorities[id][_qos],
213 (dir == READ) ? readQueueSizes[_qos]: writeQueueSizes[_qos]);
214}
215
216uint8_t
218{
219 if (policy) {
220 return policy->schedule(id, data);
221 } else {
222 DPRINTF(QOS,
223 "qos::MemCtrl::schedule requestor id [%d] "
224 "data received [%d], but QoS scheduler not initialized\n",
225 id,data);
226 return 0;
227 }
228}
229
230uint8_t
232{
233 assert(pkt->req);
234
235 if (policy) {
236 return schedule(pkt->req->requestorId(), pkt->getSize());
237 } else {
238 DPRINTF(QOS, "qos::MemCtrl::schedule Packet received [Qv %d], "
239 "but QoS scheduler not initialized\n",
240 pkt->qosValue());
241 return pkt->qosValue();
242 }
243}
244
247{
248 auto bus_state = getBusState();
249
250 if (turnPolicy) {
251 DPRINTF(QOS,
252 "qos::MemCtrl::selectNextBusState running policy %s\n",
253 turnPolicy->name());
254
255 bus_state = turnPolicy->selectBusState();
256 } else {
257 DPRINTF(QOS,
258 "qos::MemCtrl::selectNextBusState running "
259 "default bus direction selection policy\n");
260
261 if ((!getTotalReadQueueSize() && bus_state == MemCtrl::READ) ||
262 (!getTotalWriteQueueSize() && bus_state == MemCtrl::WRITE)) {
263 // READ/WRITE turnaround
264 bus_state = (bus_state == MemCtrl::READ) ? MemCtrl::WRITE :
266
267 }
268 }
269
270 return bus_state;
271}
272
273void
275{
276 if (!hasRequestor(id)) {
277 requestors.emplace(id, _system->getRequestorName(id));
278 packetPriorities[id].resize(numPriorities(), 0);
279
280 DPRINTF(QOS,
281 "qos::MemCtrl::addRequestor registering"
282 " Requestor %s [id %d]\n",
283 requestors[id], id);
284 }
285}
286
288 : statistics::Group(&mc),
289 memCtrl(mc),
290
291 ADD_STAT(avgPriority, statistics::units::Count::get(),
292 "Average QoS priority value for accepted requests"),
293 ADD_STAT(avgPriorityDistance, statistics::units::Count::get(),
294 "Average QoS priority distance between assigned and queued "
295 "values"),
296
297 ADD_STAT(priorityMinLatency, statistics::units::Second::get(),
298 "per QoS priority minimum request to response latency"),
299 ADD_STAT(priorityMaxLatency, statistics::units::Second::get(),
300 "per QoS priority maximum request to response latency"),
301 ADD_STAT(numReadWriteTurnArounds, statistics::units::Count::get(),
302 "Number of turnarounds from READ to WRITE"),
303 ADD_STAT(numWriteReadTurnArounds, statistics::units::Count::get(),
304 "Number of turnarounds from WRITE to READ"),
305 ADD_STAT(numStayReadState, statistics::units::Count::get(),
306 "Number of times bus staying in READ state"),
307 ADD_STAT(numStayWriteState, statistics::units::Count::get(),
308 "Number of times bus staying in WRITE state")
309{
310}
311
312void
314{
316
317 using namespace statistics;
318
319 System *system = memCtrl._system;
320 const auto max_requestors = system->maxRequestors();
321 const auto num_priorities = memCtrl.numPriorities();
322
323 // Initializes per requestor statistics
324 avgPriority
325 .init(max_requestors)
326 .flags(nozero | nonan)
327 .precision(2)
328 ;
329
330 avgPriorityDistance
331 .init(max_requestors)
332 .flags(nozero | nonan)
333 ;
334
335 priorityMinLatency
336 .init(num_priorities)
337 .precision(12)
338 ;
339
340 priorityMaxLatency
341 .init(num_priorities)
342 .precision(12)
343 ;
344
345 for (int i = 0; i < max_requestors; i++) {
346 const std::string name = system->getRequestorName(i);
347 avgPriority.subname(i, name);
348 avgPriorityDistance.subname(i, name);
349 }
350
351 for (int j = 0; j < num_priorities; ++j) {
352 priorityMinLatency.subname(j, std::to_string(j));
353 priorityMaxLatency.subname(j, std::to_string(j));
354 }
355}
356
357void
359{
360 if (busStateNext != busState) {
361 if (busState == READ) {
363 } else if (busState == WRITE) {
365 }
366 } else {
367 if (busState == READ) {
369 } else if (busState == WRITE) {
371 }
372 }
373}
374
375} // namespace qos
376} // namespace memory
377} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
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
uint8_t qosValue() const
QoS Value getter Returns 0 if QoS value was never set (constructor default).
Definition packet.hh:769
RequestPtr req
A pointer to the original request.
Definition packet.hh:377
unsigned getSize() const
Definition packet.hh:817
std::string getRequestorName(RequestorID requestor_id)
Get the name of an object for a given request id.
Definition system.cc:526
RequestorID maxRequestors()
Get the number of requestors registered in the system.
Definition system.hh:495
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
BusState getBusState() const
Gets the current bus state.
Definition mem_ctrl.hh:296
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
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
std::vector< Tick > serviceTick
Vector of QoS priorities/last service time.
Definition mem_ctrl.hh:121
std::unordered_map< RequestorID, std::vector< uint64_t > > packetPriorities
Hash of requestors - number of packets queued per priority.
Definition mem_ctrl.hh:111
std::vector< uint64_t > readQueueSizes
Read request packets queue length in #packets, per QoS priority.
Definition mem_ctrl.hh:124
const std::unique_ptr< Policy > policy
QoS Policy, assigns QoS priority to the incoming packets.
Definition mem_ctrl.hh:87
const std::unique_ptr< QueuePolicy > queuePolicy
QoS Queue Policy: selects packet among same-priority queue.
Definition mem_ctrl.hh:93
MemCtrl(const QoSMemCtrlParams &)
QoS Memory base class.
Definition mem_ctrl.cc:54
BusState selectNextBusState()
Returns next bus direction (READ or WRITE) based on configured policy.
Definition mem_ctrl.cc:246
const std::unique_ptr< TurnaroundPolicy > turnPolicy
QoS Bus Turnaround Policy: selects the bus direction (READ/WRITE)
Definition mem_ctrl.hh:90
bool hasRequestor(RequestorID id) const
hasRequestor returns true if the selected requestor(ID) has been registered in the memory controller,...
Definition mem_ctrl.hh:315
uint8_t numPriorities() const
Gets the total number of priority levels in the QoS memory controller.
Definition mem_ctrl.hh:366
uint64_t getTotalWriteQueueSize() const
Gets the total combined WRITE queues size.
Definition mem_ctrl.hh:350
const uint8_t _numPriorities
Number of configured QoS priorities.
Definition mem_ctrl.hh:96
void addRequestor(const RequestorID id)
Initializes dynamically counters and statistics for a given Requestor.
Definition mem_ctrl.cc:274
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
std::unordered_map< RequestorID, std::unordered_map< uint64_t, std::deque< uint64_t > > > requestTimes
Hash of requestors - address of request - queue of times of request.
Definition mem_ctrl.hh:115
gem5::memory::qos::MemCtrl::MemCtrlStats stats
System * system() const
read the system pointer
Definition mem_ctrl.hh:370
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
uint64_t getTotalReadQueueSize() const
Gets the total combined READ queues size.
Definition mem_ctrl.hh:343
std::unordered_map< RequestorID, const std::string > requestors
Hash of requestor ID - requestor name.
Definition mem_ctrl.hh:108
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
Statistics container.
Definition group.hh:93
void value(VCounter &vec) const
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
#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 void regStats()
Callback to set stat parameters.
Definition group.cc:68
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 33 > id
Bitfield< 0 > p
Bitfield< 15 > system
Definition misc.hh:1032
Bitfield< 3 > addr
Definition types.hh:84
double s
These variables equal the number of ticks in the unit of time they're named after in a double.
Definition core.cc:51
const FlagsType nonan
Don't print if this is NAN.
Definition info.hh:69
const FlagsType nozero
Don't print if this is zero.
Definition info.hh:67
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
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
uint16_t RequestorID
Definition request.hh:95
statistics::VectorStandardDeviation avgPriorityDistance
per-requestor average QoS distance between assigned and queued values
Definition mem_ctrl.hh:158
statistics::VectorStandardDeviation avgPriority
per-requestor average QoS priority
Definition mem_ctrl.hh:153
statistics::Vector priorityMaxLatency
per-priority maximum latency
Definition mem_ctrl.hh:163
statistics::Vector priorityMinLatency
per-priority minimum latency
Definition mem_ctrl.hh:161
statistics::Scalar numStayReadState
Count the number of times bus staying in READ state.
Definition mem_ctrl.hh:169
statistics::Scalar numReadWriteTurnArounds
Count the number of turnarounds READ to WRITE.
Definition mem_ctrl.hh:165
void regStats() override
Callback to set stat parameters.
Definition mem_ctrl.cc:313
statistics::Scalar numStayWriteState
Count the number of times bus staying in WRITE state.
Definition mem_ctrl.hh:171
statistics::Scalar numWriteReadTurnArounds
Count the number of turnarounds WRITE to READ.
Definition mem_ctrl.hh:167
Definition mem.h:38

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