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

Generated on Wed Sep 30 2020 14:02:13 for gem5 by doxygen 1.8.17