base.cc revision 2810
11196Shsul@eecs.umich.edu/*
21196Shsul@eecs.umich.edu * Copyright (c) 2005 The Regents of The University of Michigan
31196Shsul@eecs.umich.edu * All rights reserved.
41196Shsul@eecs.umich.edu *
51196Shsul@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
61196Shsul@eecs.umich.edu * modification, are permitted provided that the following conditions are
71196Shsul@eecs.umich.edu * met: redistributions of source code must retain the above copyright
81196Shsul@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
91196Shsul@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
101196Shsul@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
111196Shsul@eecs.umich.edu * documentation and/or other materials provided with the distribution;
121196Shsul@eecs.umich.edu * neither the name of the copyright holders nor the names of its
131362Shsul@eecs.umich.edu * contributors may be used to endorse or promote products derived from
141648Sbinkertn@umich.edu * this software without specific prior written permission.
151196Shsul@eecs.umich.edu *
161196Shsul@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171196Shsul@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181196Shsul@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191196Shsul@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201196Shsul@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211196Shsul@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221196Shsul@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231196Shsul@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241196Shsul@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251196Shsul@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261196Shsul@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271645Srdreslin@umich.edu *
281645Srdreslin@umich.edu * Authors: Ron Dreslinski
291196Shsul@eecs.umich.edu */
301196Shsul@eecs.umich.edu
311196Shsul@eecs.umich.edu/**
321196Shsul@eecs.umich.edu * @file
331196Shsul@eecs.umich.edu * Hardware Prefetcher Definition.
341196Shsul@eecs.umich.edu */
351196Shsul@eecs.umich.edu
361196Shsul@eecs.umich.edu#include "base/trace.hh"
371196Shsul@eecs.umich.edu#include "mem/cache/base_cache.hh"
381196Shsul@eecs.umich.edu#include "mem/cache/prefetch/base_prefetcher.hh"
391196Shsul@eecs.umich.edu#include <list>
401196Shsul@eecs.umich.edu
411196Shsul@eecs.umich.eduBasePrefetcher::BasePrefetcher(int size, bool pageStop, bool serialSquash,
421196Shsul@eecs.umich.edu                               bool cacheCheckPush, bool onlyData)
431196Shsul@eecs.umich.edu    :size(size), pageStop(pageStop), serialSquash(serialSquash),
441196Shsul@eecs.umich.edu     cacheCheckPush(cacheCheckPush), only_data(onlyData)
451196Shsul@eecs.umich.edu{
461196Shsul@eecs.umich.edu}
471196Shsul@eecs.umich.edu
481196Shsul@eecs.umich.eduvoid
491196Shsul@eecs.umich.eduBasePrefetcher::setCache(BaseCache *_cache)
501196Shsul@eecs.umich.edu{
511196Shsul@eecs.umich.edu    cache = _cache;
521648Sbinkertn@umich.edu    blkSize = cache->getBlockSize();
531196Shsul@eecs.umich.edu}
541196Shsul@eecs.umich.edu
551196Shsul@eecs.umich.eduvoid
561196Shsul@eecs.umich.eduBasePrefetcher::regStats(const std::string &name)
57{
58    pfIdentified
59        .name(name + ".prefetcher.num_hwpf_identified")
60        .desc("number of hwpf identified")
61        ;
62
63    pfMSHRHit
64        .name(name + ".prefetcher.num_hwpf_already_in_mshr")
65        .desc("number of hwpf that were already in mshr")
66        ;
67
68    pfCacheHit
69        .name(name + ".prefetcher.num_hwpf_already_in_cache")
70        .desc("number of hwpf that were already in the cache")
71        ;
72
73    pfBufferHit
74        .name(name + ".prefetcher.num_hwpf_already_in_prefetcher")
75        .desc("number of hwpf that were already in the prefetch queue")
76        ;
77
78    pfRemovedFull
79        .name(name + ".prefetcher.num_hwpf_evicted")
80        .desc("number of hwpf removed due to no buffer left")
81        ;
82
83    pfRemovedMSHR
84        .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit")
85        .desc("number of hwpf removed because MSHR allocated")
86        ;
87
88    pfIssued
89        .name(name + ".prefetcher.num_hwpf_issued")
90        .desc("number of hwpf issued")
91        ;
92
93    pfSpanPage
94        .name(name + ".prefetcher.num_hwpf_span_page")
95        .desc("number of hwpf spanning a virtual page")
96        ;
97
98    pfSquashed
99        .name(name + ".prefetcher.num_hwpf_squashed_from_miss")
100        .desc("number of hwpf that got squashed due to a miss aborting calculation time")
101        ;
102}
103
104Packet *
105BasePrefetcher::getPacket()
106{
107    DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name());
108
109    if (pf.empty()) {
110        DPRINTF(HWPrefetch, "%s:No HW_PF found\n", cache->name());
111        return NULL;
112    }
113
114    Packet * pkt;
115    bool keepTrying = false;
116    do {
117        pkt = *pf.begin();
118        pf.pop_front();
119        if (!cacheCheckPush) {
120            keepTrying = inCache(pkt);
121        }
122        if (pf.empty()) {
123            cache->clearMasterRequest(Request_PF);
124            if (keepTrying) return NULL; //None left, all were in cache
125        }
126    } while (keepTrying);
127
128    pfIssued++;
129    return pkt;
130}
131
132void
133BasePrefetcher::handleMiss(Packet * &pkt, Tick time)
134{
135    if (!pkt->isUncacheable() && !(pkt->isInstRead() && only_data))
136    {
137        //Calculate the blk address
138        Addr blkAddr = pkt->paddr & ~(Addr)(blkSize-1);
139
140        //Check if miss is in pfq, if so remove it
141        std::list<Packet *>::iterator iter = inPrefetch(blkAddr);
142        if (iter != pf.end()) {
143            DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name());
144            pfRemovedMSHR++;
145            pf.erase(iter);
146            if (pf.empty())
147                cache->clearMasterRequest(Request_PF);
148        }
149
150        //Remove anything in queue with delay older than time
151        //since everything is inserted in time order, start from end
152        //and work until pf.empty() or time is earlier
153        //This is done to emulate Aborting the previous work on a new miss
154        //Needed for serial calculators like GHB
155        if (serialSquash) {
156            iter = pf.end();
157            iter--;
158            while (!pf.empty() && ((*iter)->time >= time)) {
159                pfSquashed++;
160                pf.pop_back();
161                iter--;
162            }
163            if (pf.empty())
164                cache->clearMasterRequest(Request_PF);
165        }
166
167
168        std::list<Addr> addresses;
169        std::list<Tick> delays;
170        calculatePrefetch(pkt, addresses, delays);
171
172        std::list<Addr>::iterator addr = addresses.begin();
173        std::list<Tick>::iterator delay = delays.begin();
174        while (addr != addresses.end())
175        {
176            DPRINTF(HWPrefetch, "%s:Found a pf canidate, inserting into prefetch queue\n", cache->name());
177            //temp calc this here...
178            pfIdentified++;
179            //create a prefetch memreq
180            Packet * prefetch;
181            prefetch = new Packet();
182            prefetch->paddr = (*addr);
183            prefetch->size = blkSize;
184            prefetch->cmd = Hard_Prefetch;
185            prefetch->xc = pkt->xc;
186            prefetch->data = new uint8_t[blkSize];
187            prefetch->req->asid = pkt->req->asid;
188            prefetch->thread_num = pkt->thread_num;
189            prefetch->time = time + (*delay); //@todo ADD LATENCY HERE
190            //... initialize
191
192            //Check if it is already in the cache
193            if (cacheCheckPush) {
194                if (inCache(prefetch)) {
195                    addr++;
196                    delay++;
197                    continue;
198                }
199            }
200
201            //Check if it is already in the miss_queue
202            if (inMissQueue(prefetch->paddr, prefetch->req->asid)) {
203                addr++;
204                delay++;
205                continue;
206            }
207
208            //Check if it is already in the pf buffer
209            if (inPrefetch(prefetch->paddr) != pf.end()) {
210                pfBufferHit++;
211                addr++;
212                delay++;
213                continue;
214            }
215
216            //We just remove the head if we are full
217            if (pf.size() == size)
218            {
219                DPRINTF(HWPrefetch, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache->name());
220                pfRemovedFull++;
221                pf.pop_front();
222            }
223
224            pf.push_back(prefetch);
225            prefetch->flags |= CACHE_LINE_FILL;
226
227            //Make sure to request the bus, with proper delay
228            cache->setMasterRequest(Request_PF, prefetch->time);
229
230            //Increment through the list
231            addr++;
232            delay++;
233        }
234    }
235}
236
237std::list<Packet *>::iterator
238BasePrefetcher::inPrefetch(Addr address)
239{
240    //Guaranteed to only be one match, we always check before inserting
241    std::list<Packet *>::iterator iter;
242    for (iter=pf.begin(); iter != pf.end(); iter++) {
243        if (((*iter)->paddr & ~(Addr)(blkSize-1)) == address) {
244            return iter;
245        }
246    }
247    return pf.end();
248}
249
250
251