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::getPacket()
108 DPRINTF(HWPrefetch
, "%s:Requesting a hw_pf to issue\n", cache
->name());
111 DPRINTF(HWPrefetch
, "%s:No HW_PF found\n", cache
->name());
116 bool keepTrying
= false;
120 if (!cacheCheckPush
) {
121 keepTrying
= inCache(pkt
);
124 cache
->clearMasterRequest(Request_PF
);
125 if (keepTrying
) return NULL
; //None left, all were in cache
127 } while (keepTrying
);
134 BasePrefetcher::handleMiss(PacketPtr
&pkt
, Tick time
)
136 if (!pkt
->req
->isUncacheable() && !(pkt
->req
->isInstRead() && only_data
))
138 //Calculate the blk address
139 Addr blkAddr
= pkt
->getAddr() & ~(Addr
)(blkSize
-1);
141 //Check if miss is in pfq, if so remove it
142 std::list
<PacketPtr
>::iterator iter
= inPrefetch(blkAddr
);
143 if (iter
!= pf
.end()) {
144 DPRINTF(HWPrefetch
, "%s:Saw a miss to a queued prefetch, removing it\n", cache
->name());
148 cache
->clearMasterRequest(Request_PF
);
151 //Remove anything in queue with delay older than time
152 //since everything is inserted in time order, start from end
153 //and work until pf.empty() or time is earlier
154 //This is done to emulate Aborting the previous work on a new miss
155 //Needed for serial calculators like GHB
159 while (!pf
.empty() && ((*iter
)->time
>= time
)) {
165 cache
->clearMasterRequest(Request_PF
);
169 std::list
<Addr
> addresses
;
170 std::list
<Tick
> delays
;
171 calculatePrefetch(pkt
, addresses
, delays
);
173 std::list
<Addr
>::iterator addr
= addresses
.begin();
174 std::list
<Tick
>::iterator delay
= delays
.begin();
175 while (addr
!= addresses
.end())
177 DPRINTF(HWPrefetch
, "%s:Found a pf canidate, inserting into prefetch queue\n", cache
->name());
178 //temp calc this here...
180 //create a prefetch memreq
181 Request
* prefetchReq
= new Request(*addr
, blkSize
, 0);
183 prefetch
= new Packet(prefetchReq
, Packet::HardPFReq
, -1);
184 prefetch
->allocate();
185 prefetch
->req
->setThreadContext(pkt
->req
->getCpuNum(),
186 pkt
->req
->getThreadNum());
188 prefetch
->time
= time
+ (*delay
); //@todo ADD LATENCY HERE
191 //Check if it is already in the cache
192 if (cacheCheckPush
) {
193 if (inCache(prefetch
)) {
200 //Check if it is already in the miss_queue
201 if (inMissQueue(prefetch
->getAddr())) {
207 //Check if it is already in the pf buffer
208 if (inPrefetch(prefetch
->getAddr()) != pf
.end()) {
215 //We just remove the head if we are full
216 if (pf
.size() == size
)
218 DPRINTF(HWPrefetch
, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache
->name());
223 pf
.push_back(prefetch
);
224 prefetch
->flags
|= CACHE_LINE_FILL
;
226 //Make sure to request the bus, with proper delay
227 cache
->setMasterRequest(Request_PF
, prefetch
->time
);
229 //Increment through the list
236 std::list
<PacketPtr
>::iterator
237 BasePrefetcher::inPrefetch(Addr address
)
239 //Guaranteed to only be one match, we always check before inserting
240 std::list
<PacketPtr
>::iterator iter
;
241 for (iter
=pf
.begin(); iter
!= pf
.end(); iter
++) {
242 if (((*iter
)->getAddr() & ~(Addr
)(blkSize
-1)) == address
) {