gem5  v19.0.0.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-2019 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  * Authors: Matteo Andreozzi
38  */
39 
40 #include "mem_ctrl.hh"
41 
42 #include "turnaround_policy.hh"
43 
44 namespace QoS {
45 
46 MemCtrl::MemCtrl(const QoSMemCtrlParams * p)
47  : AbstractMemory(p),
48  policy(p->qos_policy),
49  turnPolicy(p->qos_turnaround_policy),
50  queuePolicy(QueuePolicy::create(p)),
51  _numPriorities(p->qos_priorities),
52  qosPriorityEscalation(p->qos_priority_escalation),
53  qosSyncroScheduler(p->qos_syncro_scheduler),
54  totalReadQueueSize(0), totalWriteQueueSize(0),
55  busState(READ), busStateNext(READ),
56  stats(*this)
57 {
58  // Set the priority policy
59  if (policy) {
60  policy->setMemCtrl(this);
61  }
62 
63  // Set the queue priority policy
64  if (queuePolicy) {
65  queuePolicy->setMemCtrl(this);
66  }
67 
68  // Set the bus turnaround policy
69  if (turnPolicy) {
70  turnPolicy->setMemCtrl(this);
71  }
72 
76 }
77 
79 {}
80 
81 void
83 {
85 }
86 
87 void
88 MemCtrl::logRequest(BusState dir, MasterID m_id, uint8_t qos,
89  Addr addr, uint64_t entries)
90 {
91  // If needed, initialize all counters and statistics
92  // for this master
93  addMaster(m_id);
94 
95  DPRINTF(QOS,
96  "QoSMemCtrl::logRequest MASTER %s [id %d] address %d"
97  " prio %d this master q packets %d"
98  " - queue size %d - requested entries %d\n",
99  masters[m_id], m_id, addr, qos, packetPriorities[m_id][qos],
100  (dir == READ) ? readQueueSizes[qos]: writeQueueSizes[qos],
101  entries);
102 
103  if (dir == READ) {
104  readQueueSizes[qos] += entries;
105  totalReadQueueSize += entries;
106  } else if (dir == WRITE) {
107  writeQueueSizes[qos] += entries;
108  totalWriteQueueSize += entries;
109  }
110 
111  packetPriorities[m_id][qos] += entries;
112  for (auto j = 0; j < entries; ++j) {
113  requestTimes[m_id][addr].push_back(curTick());
114  }
115 
116  // Record statistics
117  stats.avgPriority[m_id].sample(qos);
118 
119  // Compute avg priority distance
120 
121  for (uint8_t i = 0; i < packetPriorities[m_id].size(); ++i) {
122  uint8_t distance =
123  (abs(int(qos) - int(i))) * packetPriorities[m_id][i];
124 
125  if (distance > 0) {
126  stats.avgPriorityDistance[m_id].sample(distance);
127  DPRINTF(QOS,
128  "QoSMemCtrl::logRequest MASTER %s [id %d]"
129  " registering priority distance %d for priority %d"
130  " (packets %d)\n",
131  masters[m_id], m_id, distance, i,
132  packetPriorities[m_id][i]);
133  }
134  }
135 
136  DPRINTF(QOS,
137  "QoSMemCtrl::logRequest MASTER %s [id %d] prio %d "
138  "this master q packets %d - new queue size %d\n",
139  masters[m_id], m_id, qos, packetPriorities[m_id][qos],
140  (dir == READ) ? readQueueSizes[qos]: writeQueueSizes[qos]);
141 
142 }
143 
144 void
145 MemCtrl::logResponse(BusState dir, MasterID m_id, uint8_t qos,
146  Addr addr, uint64_t entries, double delay)
147 {
148  panic_if(!hasMaster(m_id),
149  "Logging response with invalid master\n");
150 
151  DPRINTF(QOS,
152  "QoSMemCtrl::logResponse MASTER %s [id %d] address %d prio"
153  " %d this master q packets %d"
154  " - queue size %d - requested entries %d\n",
155  masters[m_id], m_id, addr, qos, packetPriorities[m_id][qos],
156  (dir == READ) ? readQueueSizes[qos]: writeQueueSizes[qos],
157  entries);
158 
159  if (dir == READ) {
160  readQueueSizes[qos] -= entries;
161  totalReadQueueSize -= entries;
162  } else if (dir == WRITE) {
163  writeQueueSizes[qos] -= entries;
164  totalWriteQueueSize -= entries;
165  }
166 
167  panic_if(packetPriorities[m_id][qos] == 0,
168  "QoSMemCtrl::logResponse master %s negative packets for priority"
169  " %d", masters[m_id], qos);
170 
171  packetPriorities[m_id][qos] -= entries;
172 
173  for (auto j = 0; j < entries; ++j) {
174  auto it = requestTimes[m_id].find(addr);
175  panic_if(it == requestTimes[m_id].end(),
176  "QoSMemCtrl::logResponse master %s unmatched response for"
177  " address %d received", masters[m_id], addr);
178 
179  // Load request time
180  uint64_t requestTime = it->second.front();
181 
182  // Remove request entry
183  it->second.pop_front();
184 
185  // Remove whole address entry if last one
186  if (it->second.empty()) {
187  requestTimes[m_id].erase(it);
188  }
189  // Compute latency
190  double latency = (double) (curTick() + delay - requestTime)
192 
193  if (latency > 0) {
194  // Record per-priority latency stats
195  if (stats.priorityMaxLatency[qos].value() < latency) {
196  stats.priorityMaxLatency[qos] = latency;
197  }
198 
199  if (stats.priorityMinLatency[qos].value() > latency
200  || stats.priorityMinLatency[qos].value() == 0) {
201  stats.priorityMinLatency[qos] = latency;
202  }
203  }
204  }
205 
206  DPRINTF(QOS,
207  "QoSMemCtrl::logResponse MASTER %s [id %d] prio %d "
208  "this master q packets %d - new queue size %d\n",
209  masters[m_id], m_id, qos, packetPriorities[m_id][qos],
210  (dir == READ) ? readQueueSizes[qos]: writeQueueSizes[qos]);
211 }
212 
213 uint8_t
215 {
216  if (policy) {
217  return policy->schedule(m_id, data);
218  } else {
219  DPRINTF(QOS,
220  "QoSScheduler::schedule master ID [%d] "
221  "data received [%d], but QoS scheduler not initialized\n",
222  m_id,data);
223  return 0;
224  }
225 }
226 
227 uint8_t
229 {
230  assert(pkt->req);
231 
232  if (policy) {
233  return schedule(pkt->req->masterId(), pkt->getSize());
234  } else {
235  DPRINTF(QOS, "QoSScheduler::schedule Packet received [Qv %d], "
236  "but QoS scheduler not initialized\n",
237  pkt->qosValue());
238  return pkt->qosValue();
239  }
240 }
241 
244 {
245  auto bus_state = getBusState();
246 
247  if (turnPolicy) {
248  DPRINTF(QOS,
249  "QoSMemoryTurnaround::selectBusState running policy %s\n",
250  turnPolicy->name());
251 
252  bus_state = turnPolicy->selectBusState();
253  } else {
254  DPRINTF(QOS,
255  "QoSMemoryTurnaround::selectBusState running "
256  "default bus direction selection policy\n");
257 
258  if ((!getTotalReadQueueSize() && bus_state == MemCtrl::READ) ||
259  (!getTotalWriteQueueSize() && bus_state == MemCtrl::WRITE)) {
260  // READ/WRITE turnaround
261  bus_state = (bus_state == MemCtrl::READ) ? MemCtrl::WRITE :
263 
264  }
265  }
266 
267  return bus_state;
268 }
269 
270 void
272 {
273  if (!hasMaster(m_id)) {
274  masters.emplace(m_id, _system->getMasterName(m_id));
275  packetPriorities[m_id].resize(numPriorities(), 0);
276 
277  DPRINTF(QOS,
278  "QoSMemCtrl::addMaster registering"
279  " Master %s [id %d]\n",
280  masters[m_id], m_id);
281  }
282 }
283 
285  : Stats::Group(&mc),
286  memCtrl(mc),
287 
288  ADD_STAT(avgPriority,
289  "Average QoS priority value for accepted requests"),
290  ADD_STAT(avgPriorityDistance,
291  "Average QoS priority distance between assigned and "
292  "queued values"),
293 
294  ADD_STAT(priorityMinLatency,
295  "per QoS priority minimum request to response latency (s)"),
296  ADD_STAT(priorityMaxLatency,
297  "per QoS priority maximum request to response latency (s)"),
298  ADD_STAT(numReadWriteTurnArounds,
299  "Number of turnarounds from READ to WRITE"),
300  ADD_STAT(numWriteReadTurnArounds,
301  "Number of turnarounds from WRITE to READ"),
302  ADD_STAT(numStayReadState,
303  "Number of times bus staying in READ state"),
304  ADD_STAT(numStayWriteState,
305  "Number of times bus staying in WRITE state")
306 {
307 }
308 
309 void
311 {
313 
314  using namespace Stats;
315 
317  const auto max_masters = system->maxMasters();
318  const auto num_priorities = memCtrl.numPriorities();
319 
320  // Initializes per master statistics
322  .init(max_masters)
323  .flags(nozero | nonan)
324  .precision(2)
325  ;
326 
328  .init(max_masters)
329  .flags(nozero | nonan)
330  ;
331 
333  .init(num_priorities)
334  .precision(12)
335  ;
336 
338  .init(num_priorities)
339  .precision(12)
340  ;
341 
342  for (int i = 0; i < max_masters; i++) {
343  const std::string master = system->getMasterName(i);
344  avgPriority.subname(i, master);
345  avgPriorityDistance.subname(i, master);
346  }
347 
348  for (int j = 0; j < num_priorities; ++j) {
351  }
352 }
353 
354 void
356 {
357  if (busStateNext != busState) {
358  if (busState == READ) {
359  stats.numWriteReadTurnArounds++;
360  } else if (busState == WRITE) {
361  stats.numReadWriteTurnArounds++;
362  }
363  } else {
364  if (busState == READ) {
365  stats.numStayReadState++;
366  } else if (busState == WRITE) {
367  stats.numStayWriteState++;
368  }
369  }
370 }
371 
372 } // namespace QoS
QoS::MemCtrl::MemCtrlStats stats
void logResponse(BusState dir, MasterID m_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:145
#define DPRINTF(x,...)
Definition: trace.hh:229
Derived & subname(off_type index, const std::string &name)
Set the subfield name for the given index, and marks this stat to print at the end of simulation...
Definition: statistics.hh:379
BusState busStateNext
bus state for next request event triggered
Definition: mem_ctrl.hh:124
Bitfield< 7 > i
std::string getMasterName(MasterID master_id)
Get the name of an object for a given request id.
Definition: system.cc:652
const std::unique_ptr< QueuePolicy > queuePolicy
QoS Queue Policy: selects packet among same-priority queue.
Definition: mem_ctrl.hh:75
uint64_t totalReadQueueSize
Total read request packets queue length in #packets.
Definition: mem_ctrl.hh:112
const FlagsType nonan
Don&#39;t print if this is NAN.
Definition: info.hh:61
Stats::Vector priorityMinLatency
per-priority minimum latency
Definition: mem_ctrl.hh:143
void addMaster(const MasterID m_id)
Initializes dynamically counters and statistics for a given Master.
Definition: mem_ctrl.cc:271
ip6_addr_t addr
Definition: inet.hh:335
virtual void regStats()
Callback to set stat parameters.
Definition: group.cc:66
void value(VCounter &vec) const
Definition: statistics.hh:1078
Definition: system.hh:77
double s
These variables equal the number of ticks in the unit of time they&#39;re named after in a double...
Definition: core.cc:52
std::vector< Tick > serviceTick
Vector of QoS priorities/last service time.
Definition: mem_ctrl.hh:103
uint8_t numPriorities() const
Gets the total number of priority levels in the QoS memory controller.
Definition: mem_ctrl.hh:350
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
Definition: statistics.hh:336
const std::unique_ptr< TurnaroundPolicy > turnPolicy
QoS Bus Turnaround Policy: selects the bus direction (READ/WRITE)
Definition: mem_ctrl.hh:72
Derived & init(size_type size)
Set this vector to have the given size.
Definition: statistics.hh:1152
std::unordered_map< MasterID, const std::string > masters
Hash of master ID - master name.
Definition: mem_ctrl.hh:90
RequestPtr req
A pointer to the original request.
Definition: packet.hh:327
MemCtrl(const QoSMemCtrlParams *)
QoS Memory base class.
Definition: mem_ctrl.cc:46
unsigned getSize() const
Definition: packet.hh:736
QoS Queue Policy.
Definition: q_policy.hh:59
Tick curTick()
The current simulated tick.
Definition: core.hh:47
Stats::VectorStandardDeviation avgPriorityDistance
per-master average QoS distance between assigned and queued values
Definition: mem_ctrl.hh:140
MemCtrlStats(MemCtrl &mc)
Definition: mem_ctrl.cc:284
std::vector< uint64_t > readQueueSizes
Read request packets queue length in #packets, per QoS priority.
Definition: mem_ctrl.hh:106
uint8_t qosValue() const
QoS Value getter Returns 0 if QoS value was never set (constructor default).
Definition: packet.hh:701
Group()=delete
BusState
Bus Direction.
Definition: mem_ctrl.hh:65
BusState busState
Bus state used to control the read/write switching and drive the scheduling of the next request...
Definition: mem_ctrl.hh:121
void recordTurnaroundStats()
Record statistics on turnarounds based on busStateNext and busState values.
Definition: mem_ctrl.cc:355
uint64_t getTotalWriteQueueSize() const
Gets the total combined WRITE queues size.
Definition: mem_ctrl.hh:334
uint64_t totalWriteQueueSize
Total write request packets queue length in #packets.
Definition: mem_ctrl.hh:115
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
bool hasMaster(MasterID m_id) const
hasMaster returns true if the selected master(ID) has been registered in the memory controller...
Definition: mem_ctrl.hh:299
uint16_t MasterID
Definition: request.hh:86
Derived & precision(int _precision)
Set the precision and marks this stat to print at the end of simulation.
Definition: statistics.hh:324
const uint8_t _numPriorities
Number of configured QoS priorities.
Definition: mem_ctrl.hh:78
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
void regStats() override
Callback to set stat parameters.
Definition: mem_ctrl.cc:310
MasterID maxMasters()
Get the number of masters registered in the system.
Definition: system.hh:412
Bitfield< 24 > j
Definition: mem_ctrl.cc:44
const MemCtrl & memCtrl
Definition: mem_ctrl.hh:132
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:69
const std::unique_ptr< Policy > policy
QoS Policy, assigns QoS priority to the incoming packets.
Definition: mem_ctrl.hh:69
void init() override
Initialise this memory.
Definition: abstract_mem.cc:71
Stats::VectorStandardDeviation avgPriority
per-master average QoS priority
Definition: mem_ctrl.hh:135
System * system() const
read the system pointer Implemented for completeness with the setter
uint64_t getTotalReadQueueSize() const
Gets the total combined READ queues size.
Definition: mem_ctrl.hh:327
void logRequest(BusState dir, MasterID m_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:88
System * _system
Pointer to the System object.
std::unordered_map< MasterID, std::unordered_map< uint64_t, std::deque< uint64_t > > > requestTimes
Hash of masters - address of request - queue of times of request.
Definition: mem_ctrl.hh:97
Stats::Vector priorityMaxLatency
per-priority maximum latency
Definition: mem_ctrl.hh:145
BusState getBusState() const
Gets the current bus state.
Definition: mem_ctrl.hh:280
An abstract memory represents a contiguous block of physical memory, with an associated address range...
void init() override
Initializes this object.
Definition: mem_ctrl.cc:82
virtual ~MemCtrl()
Definition: mem_ctrl.cc:78
std::unordered_map< MasterID, std::vector< uint64_t > > packetPriorities
Hash of masters - number of packets queued per priority.
Definition: mem_ctrl.hh:93
VectorStandardDeviation & init(size_type size)
Initialize storage for this distribution.
Definition: statistics.hh:2750
std::vector< uint64_t > writeQueueSizes
Write request packets queue length in #packets, per QoS priority.
Definition: mem_ctrl.hh:109
const FlagsType nozero
Don&#39;t print if this is zero.
Definition: info.hh:59
Bitfield< 0 > p
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:185
std::vector< Info * > stats
Definition: group.hh:177
const char data[]
The QoS::MemCtrl is a base class for Memory objects which support QoS - it provides access to a set o...
Definition: mem_ctrl.hh:61
uint8_t schedule(MasterID m_id, uint64_t data)
Definition: mem_ctrl.cc:214
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:60
BusState selectNextBusState()
Returns next bus direction (READ or WRITE) based on configured policy.
Definition: mem_ctrl.cc:243

Generated on Fri Feb 28 2020 16:27:02 for gem5 by doxygen 1.8.13