gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
queued.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2015 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: Mitch Hayenga
38  */
39 
41 
42 #include "debug/HWPrefetch.hh"
43 #include "mem/cache/base.hh"
44 
45 QueuedPrefetcher::QueuedPrefetcher(const QueuedPrefetcherParams *p)
46  : BasePrefetcher(p), queueSize(p->queue_size), latency(p->latency),
47  queueSquash(p->queue_squash), queueFilter(p->queue_filter),
48  cacheSnoop(p->cache_snoop), tagPrefetch(p->tag_prefetch)
49 {
50 
51 }
52 
54 {
55  // Delete the queued prefetch packets
56  for (DeferredPacket &p : pfq) {
57  delete p.pkt->req;
58  delete p.pkt;
59  }
60 }
61 
62 Tick
64 {
65  // Verify this access type is observed by prefetcher
66  if (observeAccess(pkt)) {
67  Addr blk_addr = pkt->getBlockAddr(blkSize);
68  bool is_secure = pkt->isSecure();
69 
70  // Squash queued prefetches if demand miss to same line
71  if (queueSquash) {
72  auto itr = pfq.begin();
73  while (itr != pfq.end()) {
74  if (itr->pkt->getAddr() == blk_addr &&
75  itr->pkt->isSecure() == is_secure) {
76  delete itr->pkt->req;
77  delete itr->pkt;
78  itr = pfq.erase(itr);
79  } else {
80  ++itr;
81  }
82  }
83  }
84 
85  // Calculate prefetches given this access
86  std::vector<AddrPriority> addresses;
87  calculatePrefetch(pkt, addresses);
88 
89  // Queue up generated prefetches
90  for (AddrPriority& pf_info : addresses) {
91 
92  // Block align prefetch address
93  pf_info.first &= ~(Addr)(blkSize - 1);
94 
95  pfIdentified++;
96  DPRINTF(HWPrefetch, "Found a pf candidate addr: %#x, "
97  "inserting into prefetch queue.\n", pf_info.first);
98 
99  // Create and insert the request
100  PacketPtr pf_pkt = insert(pf_info, is_secure);
101 
102  if (pf_pkt != nullptr) {
103  if (tagPrefetch && pkt->req->hasPC()) {
104  // Tag prefetch packet with accessing pc
105  pf_pkt->req->setPC(pkt->req->getPC());
106  }
107  }
108  }
109  }
110 
111  return pfq.empty() ? MaxTick : pfq.front().tick;
112 }
113 
114 PacketPtr
116 {
117  DPRINTF(HWPrefetch, "Requesting a prefetch to issue.\n");
118 
119  if (pfq.empty()) {
120  DPRINTF(HWPrefetch, "No hardware prefetches available.\n");
121  return nullptr;
122  }
123 
124  PacketPtr pkt = pfq.begin()->pkt;
125  pfq.pop_front();
126 
127  pfIssued++;
128  assert(pkt != nullptr);
129  DPRINTF(HWPrefetch, "Generating prefetch for %#x.\n", pkt->getAddr());
130  return pkt;
131 }
132 
134 QueuedPrefetcher::inPrefetch(Addr address, bool is_secure) const
135 {
136  for (const_iterator dp = pfq.begin(); dp != pfq.end(); dp++) {
137  if ((*dp).pkt->getAddr() == address &&
138  (*dp).pkt->isSecure() == is_secure) return dp;
139  }
140 
141  return pfq.end();
142 }
143 
145 QueuedPrefetcher::inPrefetch(Addr address, bool is_secure)
146 {
147  for (iterator dp = pfq.begin(); dp != pfq.end(); dp++) {
148  if (dp->pkt->getAddr() == address &&
149  dp->pkt->isSecure() == is_secure) return dp;
150  }
151 
152  return pfq.end();
153 }
154 
155 void
157 {
159 
161  .name(name() + ".pfIdentified")
162  .desc("number of prefetch candidates identified");
163 
165  .name(name() + ".pfBufferHit")
166  .desc("number of redundant prefetches already in prefetch queue");
167 
168  pfInCache
169  .name(name() + ".pfInCache")
170  .desc("number of redundant prefetches already in cache/mshr dropped");
171 
173  .name(name() + ".pfRemovedFull")
174  .desc("number of prefetches dropped due to prefetch queue size");
175 
176  pfSpanPage
177  .name(name() + ".pfSpanPage")
178  .desc("number of prefetches not generated due to page crossing");
179 }
180 
181 PacketPtr
182 QueuedPrefetcher::insert(AddrPriority &pf_info, bool is_secure)
183 {
184  if (queueFilter) {
185  iterator it = inPrefetch(pf_info.first, is_secure);
186  /* If the address is already in the queue, update priority and leave */
187  if (it != pfq.end()) {
188  pfBufferHit++;
189  if (it->priority < pf_info.second) {
190  /* Update priority value and position in the queue */
191  it->priority = pf_info.second;
192  iterator prev = it;
193  bool cont = true;
194  while (cont && prev != pfq.begin()) {
195  prev--;
196  /* If the packet has higher priority, swap */
197  if (*it > *prev) {
198  std::swap(*it, *prev);
199  it = prev;
200  }
201  }
202  DPRINTF(HWPrefetch, "Prefetch addr already in "
203  "prefetch queue, priority updated\n");
204  } else {
205  DPRINTF(HWPrefetch, "Prefetch addr already in "
206  "prefetch queue\n");
207  }
208  return nullptr;
209  }
210  }
211 
212  if (cacheSnoop && (inCache(pf_info.first, is_secure) ||
213  inMissQueue(pf_info.first, is_secure))) {
214  pfInCache++;
215  DPRINTF(HWPrefetch, "Dropping redundant in "
216  "cache/MSHR prefetch addr:%#x\n", pf_info.first);
217  return nullptr;
218  }
219 
220  /* Create a prefetch memory request */
221  Request *pf_req =
222  new Request(pf_info.first, blkSize, 0, masterId);
223 
224  if (is_secure) {
225  pf_req->setFlags(Request::SECURE);
226  }
228  PacketPtr pf_pkt = new Packet(pf_req, MemCmd::HardPFReq);
229  pf_pkt->allocate();
230 
231  /* Verify prefetch buffer space for request */
232  if (pfq.size() == queueSize) {
233  pfRemovedFull++;
234  /* Lowest priority packet */
235  iterator it = pfq.end();
236  panic_if (it == pfq.begin(), "Prefetch queue is both full and empty!");
237  --it;
238  /* Look for oldest in that level of priority */
239  panic_if (it == pfq.begin(), "Prefetch queue is full with 1 element!");
240  iterator prev = it;
241  bool cont = true;
242  /* While not at the head of the queue */
243  while (cont && prev != pfq.begin()) {
244  prev--;
245  /* While at the same level of priority */
246  cont = (*prev).priority == (*it).priority;
247  if (cont)
248  /* update pointer */
249  it = prev;
250  }
251  DPRINTF(HWPrefetch, "Prefetch queue full, removing lowest priority "
252  "oldest packet, addr: %#x", it->pkt->getAddr());
253  delete it->pkt->req;
254  delete it->pkt;
255  pfq.erase(it);
256  }
257 
258  Tick pf_time = curTick() + clockPeriod() * latency;
259  DPRINTF(HWPrefetch, "Prefetch queued. "
260  "addr:%#x priority: %3d tick:%lld.\n",
261  pf_info.first, pf_info.second, pf_time);
262 
263  /* Create the packet and find the spot to insert it */
264  DeferredPacket dpp(pf_time, pf_pkt, pf_info.second);
265  if (pfq.size() == 0) {
266  pfq.emplace_back(dpp);
267  } else {
268  iterator it = pfq.end();
269  while (it != pfq.begin() && dpp > *it)
270  --it;
271  /* If we reach the head, we have to see if the new element is new head
272  * or not */
273  if (it == pfq.begin() && dpp <= *it)
274  it++;
275  pfq.insert(it, dpp);
276  }
277 
278  return pf_pkt;
279 }
bool isSecure() const
Definition: packet.hh:661
#define DPRINTF(x,...)
Definition: trace.hh:212
Declares a basic cache interface BaseCache.
void setPC(Addr pc)
Definition: request.hh:701
const Cycles latency
Cycles after generation when a prefetch can first be issued.
Definition: queued.hh:80
STL pair class.
Definition: stl.hh:61
const unsigned queueSize
Maximum size of the prefetch queue.
Definition: queued.hh:77
std::list< DeferredPacket >::const_iterator inPrefetch(Addr address, bool is_secure) const
Definition: queued.cc:134
Addr getBlockAddr(unsigned int blk_size) const
Definition: packet.hh:656
panic_if(!root,"Invalid expression\n")
virtual void regStats()
Register statistics for this object.
Definition: base.cc:76
bool hasPC() const
Definition: request.hh:708
Addr getPC() const
Accessor function for pc.
Definition: request.hh:715
std::list< DeferredPacket >::const_iterator const_iterator
Definition: queued.hh:94
STL vector class.
Definition: stl.hh:40
std::list< DeferredPacket >::iterator iterator
Definition: queued.hh:97
Tick notify(const PacketPtr &pkt)
Notify prefetcher of cache access (may be any access or just misses, depending on cache parameters...
Definition: queued.cc:63
const Tick MaxTick
Definition: types.hh:65
Tick curTick()
The current simulated tick.
Definition: core.hh:47
bool observeAccess(const PacketPtr &pkt) const
Determine if this access should be observed.
Definition: base.cc:88
PacketPtr getPacket()
Definition: queued.cc:115
uint64_t Tick
Tick count type.
Definition: types.hh:63
Stats::Scalar pfRemovedFull
Definition: queued.hh:105
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:304
STL list class.
Definition: stl.hh:54
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
MasterID masterId
Request id for prefetches.
Definition: base.hh:93
bool inMissQueue(Addr addr, bool is_secure) const
Determine if address is in cache miss queue.
Definition: base.cc:122
const bool cacheSnoop
Snoop the cache before generating prefetch (cheating basically)
Definition: queued.hh:89
QueuedPrefetcher(const QueuedPrefetcherParams *p)
Definition: queued.cc:45
const bool tagPrefetch
Tag prefetch with PC of generating access?
Definition: queued.hh:92
const bool queueFilter
Filter prefetches if already queued.
Definition: queued.hh:86
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
Definition: statistics.hh:254
bool inCache(Addr addr, bool is_secure) const
Determine if address is in cache.
Definition: base.cc:113
Tick clockPeriod() const
virtual const std::string name() const
Definition: sim_object.hh:117
Stats::Scalar pfSpanPage
Definition: queued.hh:106
const bool queueSquash
Squash queued prefetch if demand access observed.
Definition: queued.hh:83
PacketPtr insert(AddrPriority &info, bool is_secure)
Definition: queued.cc:182
Stats::Scalar pfInCache
Definition: queued.hh:104
The request targets the secure memory space.
Definition: request.hh:181
virtual void calculatePrefetch(const PacketPtr &pkt, std::vector< AddrPriority > &addresses)=0
virtual ~QueuedPrefetcher()
Definition: queued.cc:53
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
Definition: statistics.hh:287
unsigned blkSize
The block size of the parent cache.
Definition: base.hh:69
Bitfield< 0 > p
Stats::Scalar pfIssued
Definition: base.hh:120
void setFlags(Flags flags)
Note that unlike other accessors, this function sets specific flags (ORs them in); it does not assign...
Definition: request.hh:595
uint32_t taskId() const
Definition: request.hh:630
void allocate()
Allocate memory for the packet.
Definition: packet.hh:1082
Stats::Scalar pfIdentified
Definition: queued.hh:102
Stats::Scalar pfBufferHit
Definition: queued.hh:103
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:102
Addr getAddr() const
Definition: packet.hh:639
void regStats()
Register statistics for this object.
Definition: queued.cc:156
std::list< DeferredPacket > pfq
Definition: queued.hh:72

Generated on Fri Jun 9 2017 13:03:48 for gem5 by doxygen 1.8.6