2 * Copyright (c) 2005 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Authors: Ron Dreslinski
33 * Hardware Prefetcher Definition.
36 #include "base/trace.hh"
37 #include "mem/cache/base_cache.hh"
38 #include "mem/cache/prefetch/base_prefetcher.hh"
39 #include "mem/request.hh"
42 BasePrefetcher::BasePrefetcher(const BaseCacheParams
*p
)
43 : size(p
->prefetcher_size
), pageStop(!p
->prefetch_past_page
),
44 serialSquash(p
->prefetch_serial_squash
),
45 cacheCheckPush(p
->prefetch_cache_check_push
),
46 only_data(p
->prefetch_data_accesses_only
)
51 BasePrefetcher::setCache(BaseCache
*_cache
)
54 blkSize
= cache
->getBlockSize();
58 BasePrefetcher::regStats(const std::string
&name
)
61 .name(name
+ ".prefetcher.num_hwpf_identified")
62 .desc("number of hwpf identified")
66 .name(name
+ ".prefetcher.num_hwpf_already_in_mshr")
67 .desc("number of hwpf that were already in mshr")
71 .name(name
+ ".prefetcher.num_hwpf_already_in_cache")
72 .desc("number of hwpf that were already in the cache")
76 .name(name
+ ".prefetcher.num_hwpf_already_in_prefetcher")
77 .desc("number of hwpf that were already in the prefetch queue")
81 .name(name
+ ".prefetcher.num_hwpf_evicted")
82 .desc("number of hwpf removed due to no buffer left")
86 .name(name
+ ".prefetcher.num_hwpf_removed_MSHR_hit")
87 .desc("number of hwpf removed because MSHR allocated")
91 .name(name
+ ".prefetcher.num_hwpf_issued")
92 .desc("number of hwpf issued")
96 .name(name
+ ".prefetcher.num_hwpf_span_page")
97 .desc("number of hwpf spanning a virtual page")
101 .name(name
+ ".prefetcher.num_hwpf_squashed_from_miss")
102 .desc("number of hwpf that got squashed due to a miss aborting calculation time")
107 BasePrefetcher::inCache(Addr addr
)
109 if (cache
->inCache(addr
)) {
117 BasePrefetcher::inMissQueue(Addr addr
)
119 if (cache
->inMissQueue(addr
)) {
127 BasePrefetcher::getPacket()
129 DPRINTF(HWPrefetch
, "%s:Requesting a hw_pf to issue\n", cache
->name());
132 DPRINTF(HWPrefetch
, "%s:No HW_PF found\n", cache
->name());
137 bool keepTrying
= false;
141 if (!cacheCheckPush
) {
142 keepTrying
= cache
->inCache(pkt
->getAddr());
145 cache
->deassertMemSideBusRequest(BaseCache::Request_PF
);
146 if (keepTrying
) return NULL
; //None left, all were in cache
148 } while (keepTrying
);
155 BasePrefetcher::handleMiss(PacketPtr
&pkt
, Tick time
)
157 if (!pkt
->req
->isUncacheable() && !(pkt
->req
->isInstRead() && only_data
))
159 //Calculate the blk address
160 Addr blkAddr
= pkt
->getAddr() & ~(Addr
)(blkSize
-1);
162 //Check if miss is in pfq, if so remove it
163 std::list
<PacketPtr
>::iterator iter
= inPrefetch(blkAddr
);
164 if (iter
!= pf
.end()) {
165 DPRINTF(HWPrefetch
, "%s:Saw a miss to a queued prefetch, removing it\n", cache
->name());
169 cache
->deassertMemSideBusRequest(BaseCache::Request_PF
);
172 //Remove anything in queue with delay older than time
173 //since everything is inserted in time order, start from end
174 //and work until pf.empty() or time is earlier
175 //This is done to emulate Aborting the previous work on a new miss
176 //Needed for serial calculators like GHB
180 while (!pf
.empty() && ((*iter
)->time
>= time
)) {
186 cache
->deassertMemSideBusRequest(BaseCache::Request_PF
);
190 std::list
<Addr
> addresses
;
191 std::list
<Tick
> delays
;
192 calculatePrefetch(pkt
, addresses
, delays
);
194 std::list
<Addr
>::iterator addr
= addresses
.begin();
195 std::list
<Tick
>::iterator delay
= delays
.begin();
196 while (addr
!= addresses
.end())
198 DPRINTF(HWPrefetch
, "%s:Found a pf canidate, inserting into prefetch queue\n", cache
->name());
199 //temp calc this here...
201 //create a prefetch memreq
202 Request
* prefetchReq
= new Request(*addr
, blkSize
, 0);
204 prefetch
= new Packet(prefetchReq
, MemCmd::HardPFReq
, -1);
205 prefetch
->allocate();
206 prefetch
->req
->setThreadContext(pkt
->req
->getCpuNum(),
207 pkt
->req
->getThreadNum());
209 prefetch
->time
= time
+ (*delay
); //@todo ADD LATENCY HERE
212 //Check if it is already in the cache
213 if (cacheCheckPush
) {
214 if (cache
->inCache(prefetch
->getAddr())) {
221 //Check if it is already in the miss_queue
222 if (cache
->inMissQueue(prefetch
->getAddr())) {
228 //Check if it is already in the pf buffer
229 if (inPrefetch(prefetch
->getAddr()) != pf
.end()) {
236 //We just remove the head if we are full
237 if (pf
.size() == size
)
239 DPRINTF(HWPrefetch
, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache
->name());
244 pf
.push_back(prefetch
);
246 //Make sure to request the bus, with proper delay
247 cache
->requestMemSideBus(BaseCache::Request_PF
, prefetch
->time
);
249 //Increment through the list
256 std::list
<PacketPtr
>::iterator
257 BasePrefetcher::inPrefetch(Addr address
)
259 //Guaranteed to only be one match, we always check before inserting
260 std::list
<PacketPtr
>::iterator iter
;
261 for (iter
=pf
.begin(); iter
!= pf
.end(); iter
++) {
262 if (((*iter
)->getAddr() & ~(Addr
)(blkSize
-1)) == address
) {