gem5 [DEVELOP-FOR-25.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),
64 stats(*this),
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"),
294 "Average QoS priority distance between assigned and queued "
295 "values"),
296
298 "per QoS priority minimum request to response latency"),
300 "per QoS priority maximum request to response latency"),
302 "Number of turnarounds from READ to WRITE"),
304 "Number of turnarounds from WRITE to READ"),
306 "Number of times bus staying in READ state"),
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
325 .init(max_requestors)
326 .flags(nozero | nonan)
327 .precision(2)
328 ;
329
331 .init(max_requestors)
332 .flags(nozero | nonan)
333 ;
334
336 .init(num_priorities)
337 .precision(12)
338 ;
339
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) {
362 stats.numWriteReadTurnArounds++;
363 } else if (busState == WRITE) {
364 stats.numReadWriteTurnArounds++;
365 }
366 } else {
367 if (busState == READ) {
368 stats.numStayReadState++;
369 } else if (busState == WRITE) {
370 stats.numStayWriteState++;
371 }
372 }
373}
374
375} // namespace qos
376} // namespace memory
377} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
const char data[]
ClockedObject(const ClockedObjectParams &p)
virtual std::string name() const
Definition named.hh:60
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
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
const bool qosPriorityEscalation
Enables QoS priority escalation.
Definition mem_ctrl.hh:99
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
const bool qosSyncroScheduler
Enables QoS synchronized scheduling invokes the QoS scheduler on all requestors, at every packet arri...
Definition mem_ctrl.hh:105
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
#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:246
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< 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
Units for Stats.
Definition units.hh:113
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 Arm Limited 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
Packet * PacketPtr
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

Generated on Mon May 26 2025 09:19:12 for gem5 by doxygen 1.13.2