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(int size
, bool pageStop
, bool serialSquash
,
43 bool cacheCheckPush
, bool onlyData
)
44 :size(size
), pageStop(pageStop
), serialSquash(serialSquash
),
45 cacheCheckPush(cacheCheckPush
), only_data(onlyData
)
50 BasePrefetcher::setCache(BaseCache
*_cache
)
53 blkSize
= cache
->getBlockSize();
57 BasePrefetcher::regStats(const std::string
&name
)
60 .name(name
+ ".prefetcher.num_hwpf_identified")
61 .desc("number of hwpf identified")
65 .name(name
+ ".prefetcher.num_hwpf_already_in_mshr")
66 .desc("number of hwpf that were already in mshr")
70 .name(name
+ ".prefetcher.num_hwpf_already_in_cache")
71 .desc("number of hwpf that were already in the cache")
75 .name(name
+ ".prefetcher.num_hwpf_already_in_prefetcher")
76 .desc("number of hwpf that were already in the prefetch queue")
80 .name(name
+ ".prefetcher.num_hwpf_evicted")
81 .desc("number of hwpf removed due to no buffer left")
85 .name(name
+ ".prefetcher.num_hwpf_removed_MSHR_hit")
86 .desc("number of hwpf removed because MSHR allocated")
90 .name(name
+ ".prefetcher.num_hwpf_issued")
91 .desc("number of hwpf issued")
95 .name(name
+ ".prefetcher.num_hwpf_span_page")
96 .desc("number of hwpf spanning a virtual page")
100 .name(name
+ ".prefetcher.num_hwpf_squashed_from_miss")
101 .desc("number of hwpf that got squashed due to a miss aborting calculation time")
106 BasePrefetcher::inCache(Addr addr
)
108 if (cache
->inCache(addr
)) {
116 BasePrefetcher::inMissQueue(Addr addr
)
118 if (cache
->inMissQueue(addr
)) {
126 BasePrefetcher::getPacket()
128 DPRINTF(HWPrefetch
, "%s:Requesting a hw_pf to issue\n", cache
->name());
131 DPRINTF(HWPrefetch
, "%s:No HW_PF found\n", cache
->name());
136 bool keepTrying
= false;
140 if (!cacheCheckPush
) {
141 keepTrying
= cache
->inCache(pkt
->getAddr());
144 cache
->clearMasterRequest(Request_PF
);
145 if (keepTrying
) return NULL
; //None left, all were in cache
147 } while (keepTrying
);
154 BasePrefetcher::handleMiss(PacketPtr
&pkt
, Tick time
)
156 if (!pkt
->req
->isUncacheable() && !(pkt
->req
->isInstRead() && only_data
))
158 //Calculate the blk address
159 Addr blkAddr
= pkt
->getAddr() & ~(Addr
)(blkSize
-1);
161 //Check if miss is in pfq, if so remove it
162 std::list
<PacketPtr
>::iterator iter
= inPrefetch(blkAddr
);
163 if (iter
!= pf
.end()) {
164 DPRINTF(HWPrefetch
, "%s:Saw a miss to a queued prefetch, removing it\n", cache
->name());
168 cache
->clearMasterRequest(Request_PF
);
171 //Remove anything in queue with delay older than time
172 //since everything is inserted in time order, start from end
173 //and work until pf.empty() or time is earlier
174 //This is done to emulate Aborting the previous work on a new miss
175 //Needed for serial calculators like GHB
179 while (!pf
.empty() && ((*iter
)->time
>= time
)) {
185 cache
->clearMasterRequest(Request_PF
);
189 std::list
<Addr
> addresses
;
190 std::list
<Tick
> delays
;
191 calculatePrefetch(pkt
, addresses
, delays
);
193 std::list
<Addr
>::iterator addr
= addresses
.begin();
194 std::list
<Tick
>::iterator delay
= delays
.begin();
195 while (addr
!= addresses
.end())
197 DPRINTF(HWPrefetch
, "%s:Found a pf canidate, inserting into prefetch queue\n", cache
->name());
198 //temp calc this here...
200 //create a prefetch memreq
201 Request
* prefetchReq
= new Request(*addr
, blkSize
, 0);
203 prefetch
= new Packet(prefetchReq
, MemCmd::HardPFReq
, -1);
204 prefetch
->allocate();
205 prefetch
->req
->setThreadContext(pkt
->req
->getCpuNum(),
206 pkt
->req
->getThreadNum());
208 prefetch
->time
= time
+ (*delay
); //@todo ADD LATENCY HERE
211 //Check if it is already in the cache
212 if (cacheCheckPush
) {
213 if (cache
->inCache(prefetch
->getAddr())) {
220 //Check if it is already in the miss_queue
221 if (cache
->inMissQueue(prefetch
->getAddr())) {
227 //Check if it is already in the pf buffer
228 if (inPrefetch(prefetch
->getAddr()) != pf
.end()) {
235 //We just remove the head if we are full
236 if (pf
.size() == size
)
238 DPRINTF(HWPrefetch
, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache
->name());
243 pf
.push_back(prefetch
);
244 prefetch
->flags
|= CACHE_LINE_FILL
;
246 //Make sure to request the bus, with proper delay
247 cache
->setMasterRequest(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
) {