sector_tags.cc revision 13215
17191Sgblack@eecs.umich.edu/*
27191Sgblack@eecs.umich.edu * Copyright (c) 2018 Inria
37191Sgblack@eecs.umich.edu * All rights reserved.
47191Sgblack@eecs.umich.edu *
57191Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67191Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77191Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87191Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97191Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107191Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117191Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127191Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137191Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147191Sgblack@eecs.umich.edu * this software without specific prior written permission.
157191Sgblack@eecs.umich.edu *
167191Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177191Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187191Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197191Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207191Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217191Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227191Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237191Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247191Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257191Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267191Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277191Sgblack@eecs.umich.edu *
287191Sgblack@eecs.umich.edu * Authors: Daniel Carvalho
297191Sgblack@eecs.umich.edu */
307191Sgblack@eecs.umich.edu
317191Sgblack@eecs.umich.edu/**
327191Sgblack@eecs.umich.edu * @file
337191Sgblack@eecs.umich.edu * Definitions of a base set associative sector tag store.
347191Sgblack@eecs.umich.edu */
357191Sgblack@eecs.umich.edu
367191Sgblack@eecs.umich.edu#include "mem/cache/tags/sector_tags.hh"
377191Sgblack@eecs.umich.edu
387191Sgblack@eecs.umich.edu#include <cassert>
397191Sgblack@eecs.umich.edu#include <memory>
407191Sgblack@eecs.umich.edu#include <string>
417191Sgblack@eecs.umich.edu
427191Sgblack@eecs.umich.edu#include "base/intmath.hh"
437191Sgblack@eecs.umich.edu#include "base/logging.hh"
447191Sgblack@eecs.umich.edu#include "base/types.hh"
457191Sgblack@eecs.umich.edu#include "debug/CacheRepl.hh"
467191Sgblack@eecs.umich.edu#include "mem/cache/base.hh"
477308Sgblack@eecs.umich.edu#include "mem/cache/replacement_policies/base.hh"
487191Sgblack@eecs.umich.edu
497316Sgblack@eecs.umich.eduSectorTags::SectorTags(const SectorTagsParams *p)
507316Sgblack@eecs.umich.edu    : BaseTags(p), assoc(p->assoc), allocAssoc(p->assoc),
517316Sgblack@eecs.umich.edu      sequentialAccess(p->sequential_access),
527316Sgblack@eecs.umich.edu      replacementPolicy(p->replacement_policy),
537316Sgblack@eecs.umich.edu      numBlocksPerSector(p->num_blocks_per_sector),
547316Sgblack@eecs.umich.edu      numSectors(numBlocks / p->num_blocks_per_sector),
557191Sgblack@eecs.umich.edu      numSets(numSectors / p->assoc),
567191Sgblack@eecs.umich.edu      blks(numBlocks), secBlks(numSectors), sets(numSets),
577191Sgblack@eecs.umich.edu      sectorShift(floorLog2(blkSize)),
587191Sgblack@eecs.umich.edu      setShift(sectorShift + floorLog2(numBlocksPerSector)),
597191Sgblack@eecs.umich.edu      tagShift(setShift + floorLog2(numSets)),
607191Sgblack@eecs.umich.edu      sectorMask(numBlocksPerSector - 1), setMask(numSets - 1)
617191Sgblack@eecs.umich.edu{
627191Sgblack@eecs.umich.edu    // Check parameters
637191Sgblack@eecs.umich.edu    fatal_if(blkSize < 4 || !isPowerOf2(blkSize),
647191Sgblack@eecs.umich.edu             "Block size must be at least 4 and a power of 2");
657191Sgblack@eecs.umich.edu    fatal_if(!isPowerOf2(numSets),
667248Sgblack@eecs.umich.edu             "# of sets must be non-zero and a power of 2");
677191Sgblack@eecs.umich.edu    fatal_if(!isPowerOf2(numBlocksPerSector),
687192Sgblack@eecs.umich.edu             "# of blocks per sector must be non-zero and a power of 2");
697192Sgblack@eecs.umich.edu    fatal_if(assoc <= 0, "associativity must be greater than zero");
707192Sgblack@eecs.umich.edu
717192Sgblack@eecs.umich.edu    // Initialize all sets
727192Sgblack@eecs.umich.edu    unsigned sec_blk_index = 0;   // index into sector blks array
737192Sgblack@eecs.umich.edu    unsigned blk_index = 0;       // index into blks array
747192Sgblack@eecs.umich.edu    for (unsigned i = 0; i < numSets; ++i) {
757192Sgblack@eecs.umich.edu        sets[i].resize(assoc);
767192Sgblack@eecs.umich.edu
777191Sgblack@eecs.umich.edu        // Initialize all sectors in this set
787191Sgblack@eecs.umich.edu        for (unsigned j = 0; j < assoc; ++j) {
797191Sgblack@eecs.umich.edu            // Select block within the set to be linked
807192Sgblack@eecs.umich.edu            SectorBlk*& sec_blk = sets[i][j];
817192Sgblack@eecs.umich.edu
827192Sgblack@eecs.umich.edu            // Locate next cache sector
837192Sgblack@eecs.umich.edu            sec_blk = &secBlks[sec_blk_index];
847192Sgblack@eecs.umich.edu
857192Sgblack@eecs.umich.edu            // Associate a replacement data entry to the sector
867192Sgblack@eecs.umich.edu            sec_blk->replacementData = replacementPolicy->instantiateEntry();
877192Sgblack@eecs.umich.edu
887192Sgblack@eecs.umich.edu            // Initialize all blocks in this sector
897192Sgblack@eecs.umich.edu            sec_blk->blks.resize(numBlocksPerSector);
907192Sgblack@eecs.umich.edu            for (unsigned k = 0; k < numBlocksPerSector; ++k){
917192Sgblack@eecs.umich.edu                // Select block within the set to be linked
927192Sgblack@eecs.umich.edu                SectorSubBlk*& blk = sec_blk->blks[k];
937192Sgblack@eecs.umich.edu
947192Sgblack@eecs.umich.edu                // Locate next cache block
957192Sgblack@eecs.umich.edu                blk = &blks[blk_index];
967192Sgblack@eecs.umich.edu
977192Sgblack@eecs.umich.edu                // Associate a data chunk to the block
987192Sgblack@eecs.umich.edu                blk->data = &dataBlks[blkSize*blk_index];
997192Sgblack@eecs.umich.edu
1007191Sgblack@eecs.umich.edu                // Associate sector block to this block
1017191Sgblack@eecs.umich.edu                blk->setSectorBlock(sec_blk);
1027191Sgblack@eecs.umich.edu
1037191Sgblack@eecs.umich.edu                // Associate the sector replacement data to this block
1047191Sgblack@eecs.umich.edu                blk->replacementData = sec_blk->replacementData;
1057191Sgblack@eecs.umich.edu
1067191Sgblack@eecs.umich.edu                // Set its set, way and sector offset
1077191Sgblack@eecs.umich.edu                blk->set = i;
1087191Sgblack@eecs.umich.edu                blk->way = j;
1097191Sgblack@eecs.umich.edu                blk->setSectorOffset(k);
1107191Sgblack@eecs.umich.edu
1117191Sgblack@eecs.umich.edu                // Update block index
1127191Sgblack@eecs.umich.edu                ++blk_index;
1137191Sgblack@eecs.umich.edu            }
1147191Sgblack@eecs.umich.edu
1157191Sgblack@eecs.umich.edu            // Update sector block index
1167248Sgblack@eecs.umich.edu            ++sec_blk_index;
1177191Sgblack@eecs.umich.edu        }
1187192Sgblack@eecs.umich.edu    }
1197192Sgblack@eecs.umich.edu}
1207192Sgblack@eecs.umich.edu
1217192Sgblack@eecs.umich.eduvoid
1227192Sgblack@eecs.umich.eduSectorTags::invalidate(CacheBlk *blk)
1237192Sgblack@eecs.umich.edu{
1247192Sgblack@eecs.umich.edu    BaseTags::invalidate(blk);
1257192Sgblack@eecs.umich.edu
1267192Sgblack@eecs.umich.edu    // Get block's sector
1277192Sgblack@eecs.umich.edu    SectorSubBlk* sub_blk = static_cast<SectorSubBlk*>(blk);
1287192Sgblack@eecs.umich.edu    const SectorBlk* sector_blk = sub_blk->getSectorBlock();
1297192Sgblack@eecs.umich.edu
1307192Sgblack@eecs.umich.edu    // When a block in a sector is invalidated, it does not make the tag
1317192Sgblack@eecs.umich.edu    // invalid automatically, as there might be other blocks in the sector
1327191Sgblack@eecs.umich.edu    // using it. The tag is invalidated only when there is a single block
1337192Sgblack@eecs.umich.edu    // in the sector.
1347192Sgblack@eecs.umich.edu    if (!sector_blk->isValid()) {
1357192Sgblack@eecs.umich.edu        // Decrease the number of tags in use
1367192Sgblack@eecs.umich.edu        tagsInUse--;
1377192Sgblack@eecs.umich.edu
1387192Sgblack@eecs.umich.edu        // Invalidate replacement data, as we're invalidating the sector
1397192Sgblack@eecs.umich.edu        replacementPolicy->invalidate(sector_blk->replacementData);
1407192Sgblack@eecs.umich.edu    }
1417192Sgblack@eecs.umich.edu}
1427192Sgblack@eecs.umich.edu
1437192Sgblack@eecs.umich.eduCacheBlk*
1447192Sgblack@eecs.umich.eduSectorTags::accessBlock(Addr addr, bool is_secure, Cycles &lat)
1457192Sgblack@eecs.umich.edu{
1467192Sgblack@eecs.umich.edu    CacheBlk *blk = findBlock(addr, is_secure);
1477192Sgblack@eecs.umich.edu
1487192Sgblack@eecs.umich.edu    // Access all tags in parallel, hence one in each way.  The data side
1497192Sgblack@eecs.umich.edu    // either accesses all blocks in parallel, or one block sequentially on
1507192Sgblack@eecs.umich.edu    // a hit.  Sequential access with a miss doesn't access data.
1517192Sgblack@eecs.umich.edu    tagAccesses += allocAssoc;
1527192Sgblack@eecs.umich.edu    if (sequentialAccess) {
1537192Sgblack@eecs.umich.edu        if (blk != nullptr) {
1547192Sgblack@eecs.umich.edu            dataAccesses += 1;
1557192Sgblack@eecs.umich.edu        }
1567192Sgblack@eecs.umich.edu    } else {
1577192Sgblack@eecs.umich.edu        dataAccesses += allocAssoc*numBlocksPerSector;
1587192Sgblack@eecs.umich.edu    }
1597192Sgblack@eecs.umich.edu
1607192Sgblack@eecs.umich.edu    if (blk != nullptr) {
1617192Sgblack@eecs.umich.edu        // If a cache hit
1627192Sgblack@eecs.umich.edu        lat = accessLatency;
1637191Sgblack@eecs.umich.edu        // Check if the block to be accessed is available. If not,
1647191Sgblack@eecs.umich.edu        // apply the accessLatency on top of block->whenReady.
1657191Sgblack@eecs.umich.edu        if (blk->whenReady > curTick() &&
1667191Sgblack@eecs.umich.edu            cache->ticksToCycles(blk->whenReady - curTick()) >
1677191Sgblack@eecs.umich.edu            accessLatency) {
1687191Sgblack@eecs.umich.edu            lat = cache->ticksToCycles(blk->whenReady - curTick()) +
1697191Sgblack@eecs.umich.edu            accessLatency;
1707191Sgblack@eecs.umich.edu        }
1717314Sgblack@eecs.umich.edu
1727314Sgblack@eecs.umich.edu        // Update number of references to accessed block
1737314Sgblack@eecs.umich.edu        blk->refCount++;
1747314Sgblack@eecs.umich.edu
1757314Sgblack@eecs.umich.edu        // Get block's sector
1767314Sgblack@eecs.umich.edu        SectorSubBlk* sub_blk = static_cast<SectorSubBlk*>(blk);
1777314Sgblack@eecs.umich.edu        const SectorBlk* sector_blk = sub_blk->getSectorBlock();
1787314Sgblack@eecs.umich.edu
1797314Sgblack@eecs.umich.edu        // Update replacement data of accessed block, which is shared with
1807314Sgblack@eecs.umich.edu        // the whole sector it belongs to
1817314Sgblack@eecs.umich.edu        replacementPolicy->touch(sector_blk->replacementData);
1827314Sgblack@eecs.umich.edu    } else {
1837314Sgblack@eecs.umich.edu        // If a cache miss
1847314Sgblack@eecs.umich.edu        lat = lookupLatency;
1857314Sgblack@eecs.umich.edu    }
1867314Sgblack@eecs.umich.edu
1877314Sgblack@eecs.umich.edu    return blk;
1887314Sgblack@eecs.umich.edu}
1897314Sgblack@eecs.umich.edu
1907314Sgblack@eecs.umich.educonst std::vector<SectorBlk*>
1917314Sgblack@eecs.umich.eduSectorTags::getPossibleLocations(Addr addr) const
1927314Sgblack@eecs.umich.edu{
1937314Sgblack@eecs.umich.edu    return sets[extractSet(addr)];
1947314Sgblack@eecs.umich.edu}
1957314Sgblack@eecs.umich.edu
1967314Sgblack@eecs.umich.eduvoid
1977314Sgblack@eecs.umich.eduSectorTags::insertBlock(const Addr addr, const bool is_secure,
1987314Sgblack@eecs.umich.edu                        const int src_master_ID, const uint32_t task_ID,
1997191Sgblack@eecs.umich.edu                        CacheBlk *blk)
2007293Sgblack@eecs.umich.edu{
2017293Sgblack@eecs.umich.edu    // Do common block insertion functionality
2027293Sgblack@eecs.umich.edu    BaseTags::insertBlock(addr, is_secure, src_master_ID, task_ID, blk);
2037293Sgblack@eecs.umich.edu
2047293Sgblack@eecs.umich.edu    // Get block's sector
2057293Sgblack@eecs.umich.edu    SectorSubBlk* sub_blk = static_cast<SectorSubBlk*>(blk);
2067293Sgblack@eecs.umich.edu    const SectorBlk* sector_blk = sub_blk->getSectorBlock();
2077293Sgblack@eecs.umich.edu
2087293Sgblack@eecs.umich.edu    // When a block is inserted, the tag is only a newly used tag if the
2097293Sgblack@eecs.umich.edu    // sector was not previously present in the cache.
2107293Sgblack@eecs.umich.edu    // This assumes BaseTags::insertBlock does not set the valid bit.
2117293Sgblack@eecs.umich.edu    if (sector_blk->isValid()) {
2127293Sgblack@eecs.umich.edu        // An existing entry's replacement data is just updated
2137293Sgblack@eecs.umich.edu        replacementPolicy->touch(sector_blk->replacementData);
2147293Sgblack@eecs.umich.edu    } else {
2157293Sgblack@eecs.umich.edu        // Increment tag counter
2167293Sgblack@eecs.umich.edu        tagsInUse++;
2177293Sgblack@eecs.umich.edu
2187293Sgblack@eecs.umich.edu        // A new entry resets the replacement data
2197293Sgblack@eecs.umich.edu        replacementPolicy->reset(sector_blk->replacementData);
2207293Sgblack@eecs.umich.edu    }
2217293Sgblack@eecs.umich.edu}
2227293Sgblack@eecs.umich.edu
2237293Sgblack@eecs.umich.eduCacheBlk*
2247293Sgblack@eecs.umich.eduSectorTags::findBlock(Addr addr, bool is_secure) const
2257293Sgblack@eecs.umich.edu{
2267293Sgblack@eecs.umich.edu    // Extract sector tag
2277191Sgblack@eecs.umich.edu    const Addr tag = extractTag(addr);
2287191Sgblack@eecs.umich.edu
2297191Sgblack@eecs.umich.edu    // The address can only be mapped to a specific location of a sector
2307191Sgblack@eecs.umich.edu    // due to sectors being composed of contiguous-address entries
2317191Sgblack@eecs.umich.edu    const Addr offset = extractSectorOffset(addr);
2327191Sgblack@eecs.umich.edu
2337191Sgblack@eecs.umich.edu    // Find all possible sector locations for the given address
2347191Sgblack@eecs.umich.edu    const std::vector<SectorBlk*> locations = getPossibleLocations(addr);
2357191Sgblack@eecs.umich.edu
2367191Sgblack@eecs.umich.edu    // Search for block
2377191Sgblack@eecs.umich.edu    for (const auto& sector : locations) {
2387191Sgblack@eecs.umich.edu        auto blk = sector->blks[offset];
2397191Sgblack@eecs.umich.edu        if (blk->getTag() == tag && blk->isValid() &&
2407191Sgblack@eecs.umich.edu            blk->isSecure() == is_secure) {
2417191Sgblack@eecs.umich.edu            return blk;
2427191Sgblack@eecs.umich.edu        }
2437191Sgblack@eecs.umich.edu    }
2447191Sgblack@eecs.umich.edu
2457191Sgblack@eecs.umich.edu    // Did not find block
2467191Sgblack@eecs.umich.edu    return nullptr;
2477191Sgblack@eecs.umich.edu}
2487191Sgblack@eecs.umich.edu
2497191Sgblack@eecs.umich.eduReplaceableEntry*
2507191Sgblack@eecs.umich.eduSectorTags::findBlockBySetAndWay(int set, int way) const
2517191Sgblack@eecs.umich.edu{
2527191Sgblack@eecs.umich.edu    return sets[set][way];
2537191Sgblack@eecs.umich.edu}
2547191Sgblack@eecs.umich.edu
2557191Sgblack@eecs.umich.eduCacheBlk*
2567191Sgblack@eecs.umich.eduSectorTags::findVictim(Addr addr, const bool is_secure,
2577191Sgblack@eecs.umich.edu                       std::vector<CacheBlk*>& evict_blks) const
2587191Sgblack@eecs.umich.edu{
2597191Sgblack@eecs.umich.edu    // Get all possible locations of this sector
2607191Sgblack@eecs.umich.edu    const std::vector<SectorBlk*> sector_locations =
2617191Sgblack@eecs.umich.edu        getPossibleLocations(addr);
2627191Sgblack@eecs.umich.edu
2637191Sgblack@eecs.umich.edu    // Check if the sector this address belongs to has been allocated
2647191Sgblack@eecs.umich.edu    Addr tag = extractTag(addr);
2657191Sgblack@eecs.umich.edu    SectorBlk* victim_sector = nullptr;
2667191Sgblack@eecs.umich.edu    for (const auto& sector : sector_locations){
2677191Sgblack@eecs.umich.edu        if ((tag == sector->getTag()) && sector->isValid() &&
2687191Sgblack@eecs.umich.edu            (is_secure == sector->isSecure())){
2697191Sgblack@eecs.umich.edu            victim_sector = sector;
2707191Sgblack@eecs.umich.edu            break;
2717191Sgblack@eecs.umich.edu        }
2727191Sgblack@eecs.umich.edu    }
2737191Sgblack@eecs.umich.edu
2747191Sgblack@eecs.umich.edu    // If the sector is not present
2757191Sgblack@eecs.umich.edu    if (victim_sector == nullptr){
2767191Sgblack@eecs.umich.edu        // Choose replacement victim from replacement candidates
2777191Sgblack@eecs.umich.edu        victim_sector = static_cast<SectorBlk*>(replacementPolicy->getVictim(
2787191Sgblack@eecs.umich.edu                          std::vector<ReplaceableEntry*>(
2797191Sgblack@eecs.umich.edu                          sector_locations.begin(), sector_locations.end())));
2807191Sgblack@eecs.umich.edu    }
2817192Sgblack@eecs.umich.edu
2827192Sgblack@eecs.umich.edu    // Get the location of the victim block within the sector
2837192Sgblack@eecs.umich.edu    SectorSubBlk* victim = victim_sector->blks[extractSectorOffset(addr)];
2847192Sgblack@eecs.umich.edu
2857192Sgblack@eecs.umich.edu    // Get evicted blocks. Blocks are only evicted if the sectors mismatch and
2867192Sgblack@eecs.umich.edu    // the currently existing sector is valid.
2877192Sgblack@eecs.umich.edu    if ((tag == victim_sector->getTag()) &&
2887192Sgblack@eecs.umich.edu        (is_secure == victim_sector->isSecure())){
2897192Sgblack@eecs.umich.edu        // It would be a hit if victim was valid, and upgrades do not call
2907192Sgblack@eecs.umich.edu        // findVictim, so it cannot happen
2917192Sgblack@eecs.umich.edu        assert(!victim->isValid());
2927192Sgblack@eecs.umich.edu    } else {
2937293Sgblack@eecs.umich.edu        // The whole sector must be evicted to make room for the new sector
2947293Sgblack@eecs.umich.edu        for (const auto& blk : victim_sector->blks){
2957293Sgblack@eecs.umich.edu            evict_blks.push_back(blk);
2967293Sgblack@eecs.umich.edu        }
2977293Sgblack@eecs.umich.edu    }
2987293Sgblack@eecs.umich.edu
2997293Sgblack@eecs.umich.edu    DPRINTF(CacheRepl, "set %x, way %x, sector offset %x: %s\n",
3007293Sgblack@eecs.umich.edu            "selecting blk for replacement\n", victim->set, victim->way,
3017314Sgblack@eecs.umich.edu            victim->getSectorOffset());
3027314Sgblack@eecs.umich.edu
3037314Sgblack@eecs.umich.edu    return victim;
3047314Sgblack@eecs.umich.edu}
3057314Sgblack@eecs.umich.edu
3067314Sgblack@eecs.umich.eduAddr
3077314Sgblack@eecs.umich.eduSectorTags::extractTag(Addr addr) const
3087314Sgblack@eecs.umich.edu{
3097314Sgblack@eecs.umich.edu    return addr >> tagShift;
3107192Sgblack@eecs.umich.edu}
3117191Sgblack@eecs.umich.edu
312int
313SectorTags::extractSet(Addr addr) const
314{
315    return (addr >> setShift) & setMask;
316}
317
318int
319SectorTags::extractSectorOffset(Addr addr) const
320{
321    return (addr >> sectorShift) & sectorMask;
322}
323
324Addr
325SectorTags::regenerateBlkAddr(const CacheBlk* blk) const
326{
327    const SectorSubBlk* blk_cast = static_cast<const SectorSubBlk*>(blk);
328    return ((blk_cast->getTag() << tagShift) | ((Addr)blk->set << setShift) |
329            ((Addr)blk_cast->getSectorOffset() << sectorShift));
330}
331
332void
333SectorTags::forEachBlk(std::function<void(CacheBlk &)> visitor)
334{
335    for (SectorSubBlk& blk : blks) {
336        visitor(blk);
337    }
338}
339
340bool
341SectorTags::anyBlk(std::function<bool(CacheBlk &)> visitor)
342{
343    for (SectorSubBlk& blk : blks) {
344        if (visitor(blk)) {
345            return true;
346        }
347    }
348    return false;
349}
350
351SectorTags *
352SectorTagsParams::create()
353{
354    return new SectorTags(this);
355}
356