fa_lru.cc revision 11870
112855Sgabeblack@google.com/*
212855Sgabeblack@google.com * Copyright (c) 2013,2016 ARM Limited
312855Sgabeblack@google.com * All rights reserved.
412855Sgabeblack@google.com *
512855Sgabeblack@google.com * The license below extends only to copyright in the software and shall
612855Sgabeblack@google.com * not be construed as granting a license to any other intellectual
712855Sgabeblack@google.com * property including but not limited to intellectual property relating
812855Sgabeblack@google.com * to a hardware implementation of the functionality of the software
912855Sgabeblack@google.com * licensed hereunder.  You may use the software subject to the license
1012855Sgabeblack@google.com * terms below provided that you ensure that this notice is replicated
1112855Sgabeblack@google.com * unmodified and in its entirety in all distributions of the software,
1212855Sgabeblack@google.com * modified or unmodified, in source code or in binary form.
1312855Sgabeblack@google.com *
1412855Sgabeblack@google.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
1512855Sgabeblack@google.com * All rights reserved.
1612855Sgabeblack@google.com *
1712855Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
1812855Sgabeblack@google.com * modification, are permitted provided that the following conditions are
1912855Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
2012855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
2112855Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
2212855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
2312855Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
2412855Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
2512855Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
2612855Sgabeblack@google.com * this software without specific prior written permission.
2712855Sgabeblack@google.com *
2812855Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2912855Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3012855Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3112855Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3212855Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3312855Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3412855Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3512855Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3612855Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3712855Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3812855Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3912855Sgabeblack@google.com *
4012855Sgabeblack@google.com * Authors: Erik Hallnor
4112855Sgabeblack@google.com */
4212855Sgabeblack@google.com
4312855Sgabeblack@google.com/**
4412855Sgabeblack@google.com * @file
4512855Sgabeblack@google.com * Definitions a fully associative LRU tagstore.
4612855Sgabeblack@google.com */
4712855Sgabeblack@google.com
4812855Sgabeblack@google.com#include "mem/cache/tags/fa_lru.hh"
4912855Sgabeblack@google.com
5012855Sgabeblack@google.com#include <cassert>
5112855Sgabeblack@google.com#include <sstream>
5212855Sgabeblack@google.com
5312855Sgabeblack@google.com#include "base/intmath.hh"
5412855Sgabeblack@google.com#include "base/misc.hh"
5512855Sgabeblack@google.com
5612855Sgabeblack@google.comusing namespace std;
5712855Sgabeblack@google.com
5812855Sgabeblack@google.comFALRU::FALRU(const Params *p)
5912855Sgabeblack@google.com    : BaseTags(p), cacheBoundaries(nullptr)
6012855Sgabeblack@google.com{
61    if (!isPowerOf2(blkSize))
62        fatal("cache block size (in bytes) `%d' must be a power of two",
63              blkSize);
64    if (!isPowerOf2(size))
65        fatal("Cache Size must be power of 2 for now");
66
67    // Track all cache sizes from 128K up by powers of 2
68    numCaches = floorLog2(size) - 17;
69    if (numCaches >0){
70        cacheBoundaries = new FALRUBlk *[numCaches];
71        cacheMask = (ULL(1) << numCaches) - 1;
72    } else {
73        cacheMask = 0;
74    }
75
76    warmupBound = size/blkSize;
77    numBlocks = size/blkSize;
78
79    blks = new FALRUBlk[numBlocks];
80    head = &(blks[0]);
81    tail = &(blks[numBlocks-1]);
82
83    head->prev = nullptr;
84    head->next = &(blks[1]);
85    head->inCache = cacheMask;
86
87    tail->prev = &(blks[numBlocks-2]);
88    tail->next = nullptr;
89    tail->inCache = 0;
90
91    unsigned index = (1 << 17) / blkSize;
92    unsigned j = 0;
93    int flags = cacheMask;
94    for (unsigned i = 1; i < numBlocks - 1; i++) {
95        blks[i].inCache = flags;
96        if (i == index - 1){
97            cacheBoundaries[j] = &(blks[i]);
98            flags &= ~ (1<<j);
99            ++j;
100            index = index << 1;
101        }
102        blks[i].prev = &(blks[i-1]);
103        blks[i].next = &(blks[i+1]);
104        blks[i].isTouched = false;
105        blks[i].set = 0;
106        blks[i].way = i;
107    }
108    assert(j == numCaches);
109    assert(index == numBlocks);
110    //assert(check());
111}
112
113FALRU::~FALRU()
114{
115    if (numCaches)
116        delete[] cacheBoundaries;
117
118    delete[] blks;
119}
120
121void
122FALRU::regStats()
123{
124    using namespace Stats;
125    BaseTags::regStats();
126    hits
127        .init(numCaches+1)
128        .name(name() + ".falru_hits")
129        .desc("The number of hits in each cache size.")
130        ;
131    misses
132        .init(numCaches+1)
133        .name(name() + ".falru_misses")
134        .desc("The number of misses in each cache size.")
135        ;
136    accesses
137        .name(name() + ".falru_accesses")
138        .desc("The number of accesses to the FA LRU cache.")
139        ;
140
141    for (unsigned i = 0; i <= numCaches; ++i) {
142        stringstream size_str;
143        if (i < 3){
144            size_str << (1<<(i+7)) <<"K";
145        } else {
146            size_str << (1<<(i-3)) <<"M";
147        }
148
149        hits.subname(i, size_str.str());
150        hits.subdesc(i, "Hits in a " + size_str.str() +" cache");
151        misses.subname(i, size_str.str());
152        misses.subdesc(i, "Misses in a " + size_str.str() +" cache");
153    }
154}
155
156FALRUBlk *
157FALRU::hashLookup(Addr addr) const
158{
159    tagIterator iter = tagHash.find(addr);
160    if (iter != tagHash.end()) {
161        return (*iter).second;
162    }
163    return nullptr;
164}
165
166void
167FALRU::invalidate(CacheBlk *blk)
168{
169    assert(blk);
170    tagsInUse--;
171}
172
173CacheBlk*
174FALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat)
175{
176    return accessBlock(addr, is_secure, lat, 0);
177}
178
179CacheBlk*
180FALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat, int *inCache)
181{
182    accesses++;
183    int tmp_in_cache = 0;
184    Addr blkAddr = blkAlign(addr);
185    FALRUBlk* blk = hashLookup(blkAddr);
186
187    if (blk && blk->isValid()) {
188        // If a cache hit
189        lat = accessLatency;
190        // Check if the block to be accessed is available. If not,
191        // apply the accessLatency on top of block->whenReady.
192        if (blk->whenReady > curTick() &&
193            cache->ticksToCycles(blk->whenReady - curTick()) >
194            accessLatency) {
195            lat = cache->ticksToCycles(blk->whenReady - curTick()) +
196            accessLatency;
197        }
198        assert(blk->tag == blkAddr);
199        tmp_in_cache = blk->inCache;
200        for (unsigned i = 0; i < numCaches; i++) {
201            if (1<<i & blk->inCache) {
202                hits[i]++;
203            } else {
204                misses[i]++;
205            }
206        }
207        hits[numCaches]++;
208        if (blk != head){
209            moveToHead(blk);
210        }
211    } else {
212        // If a cache miss
213        lat = lookupLatency;
214        blk = nullptr;
215        for (unsigned i = 0; i <= numCaches; ++i) {
216            misses[i]++;
217        }
218    }
219    if (inCache) {
220        *inCache = tmp_in_cache;
221    }
222
223    //assert(check());
224    return blk;
225}
226
227
228CacheBlk*
229FALRU::findBlock(Addr addr, bool is_secure) const
230{
231    Addr blkAddr = blkAlign(addr);
232    FALRUBlk* blk = hashLookup(blkAddr);
233
234    if (blk && blk->isValid()) {
235        assert(blk->tag == blkAddr);
236    } else {
237        blk = nullptr;
238    }
239    return blk;
240}
241
242CacheBlk*
243FALRU::findBlockBySetAndWay(int set, int way) const
244{
245    assert(set == 0);
246    return &blks[way];
247}
248
249CacheBlk*
250FALRU::findVictim(Addr addr)
251{
252    FALRUBlk * blk = tail;
253    assert(blk->inCache == 0);
254    moveToHead(blk);
255    tagHash.erase(blk->tag);
256    tagHash[blkAlign(addr)] = blk;
257    if (blk->isValid()) {
258        replacements[0]++;
259    } else {
260        tagsInUse++;
261        blk->isTouched = true;
262        if (!warmedUp && tagsInUse.value() >= warmupBound) {
263            warmedUp = true;
264            warmupCycle = curTick();
265        }
266    }
267    //assert(check());
268    return blk;
269}
270
271void
272FALRU::insertBlock(PacketPtr pkt, CacheBlk *blk)
273{
274}
275
276void
277FALRU::moveToHead(FALRUBlk *blk)
278{
279    int updateMask = blk->inCache ^ cacheMask;
280    for (unsigned i = 0; i < numCaches; i++){
281        if ((1<<i) & updateMask) {
282            cacheBoundaries[i]->inCache &= ~(1<<i);
283            cacheBoundaries[i] = cacheBoundaries[i]->prev;
284        } else if (cacheBoundaries[i] == blk) {
285            cacheBoundaries[i] = blk->prev;
286        }
287    }
288    blk->inCache = cacheMask;
289    if (blk != head) {
290        if (blk == tail){
291            assert(blk->next == nullptr);
292            tail = blk->prev;
293            tail->next = nullptr;
294        } else {
295            blk->prev->next = blk->next;
296            blk->next->prev = blk->prev;
297        }
298        blk->next = head;
299        blk->prev = nullptr;
300        head->prev = blk;
301        head = blk;
302    }
303}
304
305bool
306FALRU::check()
307{
308    FALRUBlk* blk = head;
309    int tot_size = 0;
310    int boundary = 1<<17;
311    int j = 0;
312    int flags = cacheMask;
313    while (blk) {
314        tot_size += blkSize;
315        if (blk->inCache != flags) {
316            return false;
317        }
318        if (tot_size == boundary && blk != tail) {
319            if (cacheBoundaries[j] != blk) {
320                return false;
321            }
322            flags &=~(1 << j);
323            boundary = boundary<<1;
324            ++j;
325        }
326        blk = blk->next;
327    }
328    return true;
329}
330
331FALRU *
332FALRUParams::create()
333{
334    return new FALRU(this);
335}
336
337