gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 
45 namespace gem5
46 {
47 
48 namespace memory
49 {
50 
51 namespace qos
52 {
53 
54 MemCtrl::MemCtrl(const QoSMemCtrlParams &p)
55  : ClockedObject(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 
88 {}
89 
90 void
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 
147 void
149  Addr addr, uint64_t entries, double delay)
150 {
151  panic_if(!hasRequestor(id),
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 
216 uint8_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 
230 uint8_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 
273 void
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 
312 void
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 
357 void
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
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::memory::qos::MemCtrl::totalReadQueueSize
uint64_t totalReadQueueSize
Total read request packets queue length in #packets.
Definition: mem_ctrl.hh:130
gem5::memory::qos::MemCtrl::queuePolicy
const std::unique_ptr< QueuePolicy > queuePolicy
QoS Queue Policy: selects packet among same-priority queue.
Definition: mem_ctrl.hh:93
gem5::memory::qos::MemCtrl::MemCtrlStats::numWriteReadTurnArounds
statistics::Scalar numWriteReadTurnArounds
Count the number of turnarounds WRITE to READ.
Definition: mem_ctrl.hh:167
gem5::memory::qos::MemCtrl::logResponse
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
gem5::MipsISA::misc_reg::Count
@ Count
Definition: misc.hh:94
data
const char data[]
Definition: circlebuf.test.cc:48
memory
Definition: mem.h:38
turnaround_policy.hh
gem5::memory::qos::MemCtrl::requestTimes
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::_numPriorities
const uint8_t _numPriorities
Number of configured QoS priorities.
Definition: mem_ctrl.hh:96
gem5::memory::qos::MemCtrl::MemCtrlStats::avgPriorityDistance
statistics::VectorStandardDeviation avgPriorityDistance
per-requestor average QoS distance between assigned and queued values
Definition: mem_ctrl.hh:158
gem5::memory::qos::MemCtrl::addRequestor
void addRequestor(const RequestorID id)
Initializes dynamically counters and statistics for a given Requestor.
Definition: mem_ctrl.cc:274
gem5::Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:377
gem5::memory::qos::MemCtrl::READ
@ READ
Definition: mem_ctrl.hh:83
gem5::memory::qos::QueuePolicy
QoS Queue Policy.
Definition: q_policy.hh:65
gem5::memory::qos::MemCtrl::_system
System * _system
Pointer to the System object.
Definition: mem_ctrl.hh:175
gem5::statistics::nozero
const FlagsType nozero
Don't print if this is zero.
Definition: info.hh:67
sc_dt::to_string
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:91
gem5::Packet::qosValue
uint8_t qosValue() const
QoS Value getter Returns 0 if QoS value was never set (constructor default).
Definition: packet.hh:769
gem5::memory::qos::MemCtrl::MemCtrlStats::numReadWriteTurnArounds
statistics::Scalar numReadWriteTurnArounds
Count the number of turnarounds READ to WRITE.
Definition: mem_ctrl.hh:165
gem5::memory::qos::MemCtrl::readQueueSizes
std::vector< uint64_t > readQueueSizes
Read request packets queue length in #packets, per QoS priority.
Definition: mem_ctrl.hh:124
gem5::memory::qos::MemCtrl::MemCtrlStats::numStayWriteState
statistics::Scalar numStayWriteState
Count the number of times bus staying in WRITE state.
Definition: mem_ctrl.hh:171
gem5::X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:1004
gem5::memory::qos::MemCtrl::MemCtrl
MemCtrl(const QoSMemCtrlParams &)
QoS Memory base class.
Definition: mem_ctrl.cc:54
gem5::statistics::nonan
const FlagsType nonan
Don't print if this is NAN.
Definition: info.hh:69
q_policy.hh
gem5::memory::qos::MemCtrl::writeQueueSizes
std::vector< uint64_t > writeQueueSizes
Write request packets queue length in #packets, per QoS priority.
Definition: mem_ctrl.hh:127
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
gem5::memory::qos::MemCtrl::BusState
BusState
Bus Direction.
Definition: mem_ctrl.hh:83
gem5::memory::qos::MemCtrl::getTotalWriteQueueSize
uint64_t getTotalWriteQueueSize() const
Gets the total combined WRITE queues size.
Definition: mem_ctrl.hh:350
gem5::memory::qos::MemCtrl::busStateNext
BusState busStateNext
bus state for next request event triggered
Definition: mem_ctrl.hh:142
gem5::memory::qos::MemCtrl::busState
BusState busState
Bus state used to control the read/write switching and drive the scheduling of the next request.
Definition: mem_ctrl.hh:139
gem5::memory::qos::MemCtrl::hasRequestor
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
gem5::memory::qos::MemCtrl::~MemCtrl
virtual ~MemCtrl()
Definition: mem_ctrl.cc:87
gem5::statistics::VectorBase::value
void value(VCounter &vec) const
Definition: statistics.hh:966
gem5::memory::qos::MemCtrl::turnPolicy
const std::unique_ptr< TurnaroundPolicy > turnPolicy
QoS Bus Turnaround Policy: selects the bus direction (READ/WRITE)
Definition: mem_ctrl.hh:90
gem5::ArmISA::j
Bitfield< 24 > j
Definition: misc_types.hh:57
gem5::memory::qos::MemCtrl::schedule
uint8_t schedule(RequestorID id, uint64_t data)
Definition: mem_ctrl.cc:217
gem5::System::maxRequestors
RequestorID maxRequestors()
Get the number of requestors registered in the system.
Definition: system.hh:495
gem5::System
Definition: system.hh:74
gem5::Named::name
virtual std::string name() const
Definition: named.hh:47
gem5::VegaISA::p
Bitfield< 54 > p
Definition: pagetable.hh:70
gem5::memory::qos::MemCtrl::selectNextBusState
BusState selectNextBusState()
Returns next bus direction (READ or WRITE) based on configured policy.
Definition: mem_ctrl.cc:246
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:210
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:75
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
gem5::System::getRequestorName
std::string getRequestorName(RequestorID requestor_id)
Get the name of an object for a given request id.
Definition: system.cc:526
gem5::memory::qos::MemCtrl::stats
gem5::memory::qos::MemCtrl::MemCtrlStats stats
gem5::memory::qos::MemCtrl::system
System * system() const
read the system pointer
Definition: mem_ctrl.hh:370
gem5::memory::qos::MemCtrl::totalWriteQueueSize
uint64_t totalWriteQueueSize
Total write request packets queue length in #packets.
Definition: mem_ctrl.hh:133
policy.hh
gem5::memory::qos::MemCtrl::MemCtrlStats::avgPriority
statistics::VectorStandardDeviation avgPriority
per-requestor average QoS priority
Definition: mem_ctrl.hh:153
gem5::memory::qos::MemCtrl::recordTurnaroundStats
void recordTurnaroundStats(BusState busState, BusState busStateNext)
Record statistics on turnarounds based on busStateNext and busState values.
Definition: mem_ctrl.cc:358
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::statistics::Group::regStats
virtual void regStats()
Callback to set stat parameters.
Definition: group.cc:68
gem5::ClockedObject
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Definition: clocked_object.hh:234
mem_ctrl.hh
gem5::memory::qos::MemCtrl::MemCtrlStats::regStats
void regStats() override
Callback to set stat parameters.
Definition: mem_ctrl.cc:313
panic_if
#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
gem5::memory::qos::MemCtrl::serviceTick
std::vector< Tick > serviceTick
Vector of QoS priorities/last service time.
Definition: mem_ctrl.hh:121
gem5::memory::qos::MemCtrl::getTotalReadQueueSize
uint64_t getTotalReadQueueSize() const
Gets the total combined READ queues size.
Definition: mem_ctrl.hh:343
gem5::memory::qos::MemCtrl::policy
const std::unique_ptr< Policy > policy
QoS Policy, assigns QoS priority to the incoming packets.
Definition: mem_ctrl.hh:87
gem5::memory::qos::MemCtrl::getBusState
BusState getBusState() const
Gets the current bus state.
Definition: mem_ctrl.hh:296
gem5::memory::qos::MemCtrl::packetPriorities
std::unordered_map< RequestorID, std::vector< uint64_t > > packetPriorities
Hash of requestors - number of packets queued per priority.
Definition: mem_ctrl.hh:111
core.hh
gem5::memory::qos::MemCtrl::numPriorities
uint8_t numPriorities() const
Gets the total number of priority levels in the QoS memory controller.
Definition: mem_ctrl.hh:366
gem5::memory::qos::MemCtrl::MemCtrlStats::priorityMinLatency
statistics::Vector priorityMinLatency
per-priority minimum latency
Definition: mem_ctrl.hh:161
gem5::statistics::Group
Statistics container.
Definition: group.hh:92
gem5::memory::qos::MemCtrl::WRITE
@ WRITE
Definition: mem_ctrl.hh:83
gem5::ArmISA::id
Bitfield< 33 > id
Definition: misc_types.hh:305
gem5::memory::qos::MemCtrl::MemCtrlStats::MemCtrlStats
MemCtrlStats(MemCtrl &mc)
Definition: mem_ctrl.cc:287
gem5::memory::qos::MemCtrl
The qos::MemCtrl is a base class for Memory objects which support QoS - it provides access to a set o...
Definition: mem_ctrl.hh:79
gem5::RequestorID
uint16_t RequestorID
Definition: request.hh:95
gem5::memory::qos::MemCtrl::requestors
std::unordered_map< RequestorID, const std::string > requestors
Hash of requestor ID - requestor name.
Definition: mem_ctrl.hh:108
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::memory::qos::MemCtrl::logRequest
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
gem5::memory::qos::MemCtrl::MemCtrlStats::numStayReadState
statistics::Scalar numStayReadState
Count the number of times bus staying in READ state.
Definition: mem_ctrl.hh:169
gem5::Packet::getSize
unsigned getSize() const
Definition: packet.hh:817
gem5::memory::qos::MemCtrl::MemCtrlStats::priorityMaxLatency
statistics::Vector priorityMaxLatency
per-priority maximum latency
Definition: mem_ctrl.hh:163
gem5::sim_clock::as_float::s
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
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84

Generated on Sun Jul 30 2023 01:56:58 for gem5 by doxygen 1.8.17