2 * Copyright (c) 2014 ARM Limited
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.
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.
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.
37 * Authors: Mitch Hayenga
40 #include "debug/HWPrefetch.hh"
41 #include "mem/cache/prefetch/queued.hh"
42 #include "mem/cache/base.hh"
44 QueuedPrefetcher::QueuedPrefetcher(const QueuedPrefetcherParams
*p
)
45 : BasePrefetcher(p
), queueSize(p
->queue_size
), latency(p
->latency
),
46 queueSquash(p
->queue_squash
), queueFilter(p
->queue_filter
),
47 cacheSnoop(p
->cache_snoop
), tagPrefetch(p
->tag_prefetch
)
52 QueuedPrefetcher::~QueuedPrefetcher()
54 // Delete the queued prefetch packets
55 for (DeferredPacket
&p
: pfq
) {
62 QueuedPrefetcher::notify(const PacketPtr
&pkt
)
64 // Verify this access type is observed by prefetcher
65 if (observeAccess(pkt
)) {
66 Addr blk_addr
= pkt
->getAddr() & ~(Addr
)(blkSize
- 1);
67 bool is_secure
= pkt
->isSecure();
69 // Squash queued prefetches if demand miss to same line
71 auto itr
= pfq
.begin();
72 while (itr
!= pfq
.end()) {
73 if (itr
->pkt
->getAddr() == blk_addr
&&
74 itr
->pkt
->isSecure() == is_secure
) {
84 // Calculate prefetches given this access
85 std::vector
<Addr
> addresses
;
86 calculatePrefetch(pkt
, addresses
);
88 // Queue up generated prefetches
89 for (Addr pf_addr
: addresses
) {
91 // Block align prefetch address
92 pf_addr
= pf_addr
& ~(Addr
)(blkSize
- 1);
95 DPRINTF(HWPrefetch
, "Found a pf candidate addr: %#x, "
96 "inserting into prefetch queue.\n", pf_addr
);
98 if (queueFilter
&& inPrefetch(pf_addr
, is_secure
)) {
100 DPRINTF(HWPrefetch
, "Prefetch addr already in "
105 if (cacheSnoop
&& (inCache(pf_addr
, is_secure
) ||
106 inMissQueue(pf_addr
, is_secure
))) {
108 DPRINTF(HWPrefetch
, "Dropping redundant in "
109 "cache/MSHR prefetch addr:%#x\n", pf_addr
);
113 // Create a prefetch memory request
115 new Request(pf_addr
, blkSize
, 0, masterId
);
118 pf_req
->setFlags(Request::SECURE
);
120 pf_req
->taskId(ContextSwitchTaskId::Prefetcher
);
121 PacketPtr pf_pkt
= new Packet(pf_req
, MemCmd::HardPFReq
);
124 if (pkt
->req
->hasContextId()) {
125 pf_req
->setContext(pkt
->req
->contextId());
128 if (tagPrefetch
&& pkt
->req
->hasPC()) {
129 // Tag prefetch packet with accessing pc
130 pf_pkt
->req
->setPC(pkt
->req
->getPC());
133 // Verify prefetch buffer space for request
134 if (pfq
.size() == queueSize
) {
136 PacketPtr old_pkt
= pfq
.begin()->pkt
;
137 DPRINTF(HWPrefetch
, "Prefetch queue full, removing "
138 "oldest packet addr: %#x", old_pkt
->getAddr());
144 Tick pf_time
= curTick() + clockPeriod() * latency
;
145 DPRINTF(HWPrefetch
, "Prefetch queued. "
146 "addr:%#x tick:%lld.\n", pf_addr
, pf_time
);
148 pfq
.emplace_back(pf_time
, pf_pkt
);
152 return pfq
.empty() ? MaxTick
: pfq
.front().tick
;
156 QueuedPrefetcher::getPacket()
158 DPRINTF(HWPrefetch
, "Requesting a prefetch to issue.\n");
161 DPRINTF(HWPrefetch
, "No hardware prefetches available.\n");
165 PacketPtr pkt
= pfq
.begin()->pkt
;
170 DPRINTF(HWPrefetch
, "Generating prefetch for %#x.\n", pkt
->getAddr());
175 QueuedPrefetcher::inPrefetch(Addr address
, bool is_secure
) const
177 for (const DeferredPacket
&dp
: pfq
) {
178 if (dp
.pkt
->getAddr() == address
&&
179 dp
.pkt
->isSecure() == is_secure
) return true;
186 QueuedPrefetcher::regStats()
188 BasePrefetcher::regStats();
191 .name(name() + ".pfIdentified")
192 .desc("number of prefetch candidates identified");
195 .name(name() + ".pfBufferHit")
196 .desc("number of redundant prefetches already in prefetch queue");
199 .name(name() + ".pfInCache")
200 .desc("number of redundant prefetches already in cache/mshr dropped");
203 .name(name() + ".pfRemovedFull")
204 .desc("number of prefetches dropped due to prefetch queue size");
207 .name(name() + ".pfSpanPage")
208 .desc("number of prefetches not generated due to page crossing");