1/* 2 * Copyright (c) 2013,2016,2018 ARM Limited 3 * All rights reserved. 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2003-2005 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Erik Hallnor 41 * Ron Dreslinski 42 */ 43 44/** 45 * @file 46 * Definitions of BaseTags. 47 */ 48 49#include "mem/cache/tags/base.hh" 50 51#include <cassert> 52 53#include "base/types.hh" 54#include "mem/cache/base.hh" 55#include "mem/cache/replacement_policies/replaceable_entry.hh" 56#include "mem/cache/tags/indexing_policies/base.hh" 57#include "mem/request.hh" 58#include "sim/core.hh" 59#include "sim/sim_exit.hh" 60#include "sim/system.hh" 61 62BaseTags::BaseTags(const Params *p) 63 : ClockedObject(p), blkSize(p->block_size), blkMask(blkSize - 1),
|
64 size(p->size),
65 lookupLatency(p->tag_latency),
66 accessLatency(p->sequential_access ?
67 p->tag_latency + p->data_latency :
68 std::max(p->tag_latency, p->data_latency)),
|
64 size(p->size), lookupLatency(p->tag_latency), |
65 cache(nullptr), indexingPolicy(p->indexing_policy), 66 warmupBound((p->warmup_percentage/100.0) * (p->size / p->block_size)), 67 warmedUp(false), numBlocks(p->size / p->block_size), 68 dataBlks(new uint8_t[p->size]) // Allocate data storage in one big chunk 69{ 70} 71 72void 73BaseTags::setCache(BaseCache *_cache) 74{ 75 assert(!cache); 76 cache = _cache; 77} 78 79ReplaceableEntry* 80BaseTags::findBlockBySetAndWay(int set, int way) const 81{ 82 return indexingPolicy->getEntry(set, way); 83} 84 85CacheBlk* 86BaseTags::findBlock(Addr addr, bool is_secure) const 87{ 88 // Extract block tag 89 Addr tag = extractTag(addr); 90 91 // Find possible entries that may contain the given address 92 const std::vector<ReplaceableEntry*> entries = 93 indexingPolicy->getPossibleEntries(addr); 94 95 // Search for block 96 for (const auto& location : entries) { 97 CacheBlk* blk = static_cast<CacheBlk*>(location); 98 if ((blk->tag == tag) && blk->isValid() && 99 (blk->isSecure() == is_secure)) { 100 return blk; 101 } 102 } 103 104 // Did not find block 105 return nullptr; 106} 107 108void 109BaseTags::insertBlock(const Addr addr, const bool is_secure, 110 const int src_master_ID, const uint32_t task_ID, 111 CacheBlk *blk) 112{ 113 assert(!blk->isValid()); 114 115 // Previous block, if existed, has been removed, and now we have 116 // to insert the new one 117 // Deal with what we are bringing in 118 assert(src_master_ID < cache->system->maxMasters()); 119 occupancies[src_master_ID]++; 120 121 // Insert block with tag, src master id and task id 122 blk->insert(extractTag(addr), is_secure, src_master_ID, task_ID); 123 124 // Check if cache warm up is done 125 if (!warmedUp && tagsInUse.value() >= warmupBound) { 126 warmedUp = true; 127 warmupCycle = curTick(); 128 } 129 130 // We only need to write into one tag and one data block. 131 tagAccesses += 1; 132 dataAccesses += 1; 133} 134 135Addr 136BaseTags::extractTag(const Addr addr) const 137{ 138 return indexingPolicy->extractTag(addr); 139} 140 141void 142BaseTags::cleanupRefsVisitor(CacheBlk &blk) 143{ 144 if (blk.isValid()) { 145 totalRefs += blk.refCount; 146 ++sampledRefs; 147 } 148} 149 150void 151BaseTags::cleanupRefs() 152{ 153 forEachBlk([this](CacheBlk &blk) { cleanupRefsVisitor(blk); }); 154} 155 156void 157BaseTags::computeStatsVisitor(CacheBlk &blk) 158{ 159 if (blk.isValid()) { 160 assert(blk.task_id < ContextSwitchTaskId::NumTaskId); 161 occupanciesTaskId[blk.task_id]++; 162 assert(blk.tickInserted <= curTick()); 163 Tick age = curTick() - blk.tickInserted; 164 165 int age_index; 166 if (age / SimClock::Int::us < 10) { // <10us 167 age_index = 0; 168 } else if (age / SimClock::Int::us < 100) { // <100us 169 age_index = 1; 170 } else if (age / SimClock::Int::ms < 1) { // <1ms 171 age_index = 2; 172 } else if (age / SimClock::Int::ms < 10) { // <10ms 173 age_index = 3; 174 } else 175 age_index = 4; // >10ms 176 177 ageTaskId[blk.task_id][age_index]++; 178 } 179} 180 181void 182BaseTags::computeStats() 183{ 184 for (unsigned i = 0; i < ContextSwitchTaskId::NumTaskId; ++i) { 185 occupanciesTaskId[i] = 0; 186 for (unsigned j = 0; j < 5; ++j) { 187 ageTaskId[i][j] = 0; 188 } 189 } 190 191 forEachBlk([this](CacheBlk &blk) { computeStatsVisitor(blk); }); 192} 193 194std::string 195BaseTags::print() 196{ 197 std::string str; 198 199 auto print_blk = [&str](CacheBlk &blk) { 200 if (blk.isValid()) 201 str += csprintf("\tBlock: %s\n", blk.print()); 202 }; 203 forEachBlk(print_blk); 204 205 if (str.empty()) 206 str = "no valid tags\n"; 207 208 return str; 209} 210 211void 212BaseTags::regStats() 213{ 214 ClockedObject::regStats(); 215 216 using namespace Stats; 217 218 tagsInUse 219 .name(name() + ".tagsinuse") 220 .desc("Cycle average of tags in use") 221 ; 222 223 totalRefs 224 .name(name() + ".total_refs") 225 .desc("Total number of references to valid blocks.") 226 ; 227 228 sampledRefs 229 .name(name() + ".sampled_refs") 230 .desc("Sample count of references to valid blocks.") 231 ; 232 233 avgRefs 234 .name(name() + ".avg_refs") 235 .desc("Average number of references to valid blocks.") 236 ; 237 238 avgRefs = totalRefs/sampledRefs; 239 240 warmupCycle 241 .name(name() + ".warmup_cycle") 242 .desc("Cycle when the warmup percentage was hit.") 243 ; 244 245 occupancies 246 .init(cache->system->maxMasters()) 247 .name(name() + ".occ_blocks") 248 .desc("Average occupied blocks per requestor") 249 .flags(nozero | nonan) 250 ; 251 for (int i = 0; i < cache->system->maxMasters(); i++) { 252 occupancies.subname(i, cache->system->getMasterName(i)); 253 } 254 255 avgOccs 256 .name(name() + ".occ_percent") 257 .desc("Average percentage of cache occupancy") 258 .flags(nozero | total) 259 ; 260 for (int i = 0; i < cache->system->maxMasters(); i++) { 261 avgOccs.subname(i, cache->system->getMasterName(i)); 262 } 263 264 avgOccs = occupancies / Stats::constant(numBlocks); 265 266 occupanciesTaskId 267 .init(ContextSwitchTaskId::NumTaskId) 268 .name(name() + ".occ_task_id_blocks") 269 .desc("Occupied blocks per task id") 270 .flags(nozero | nonan) 271 ; 272 273 ageTaskId 274 .init(ContextSwitchTaskId::NumTaskId, 5) 275 .name(name() + ".age_task_id_blocks") 276 .desc("Occupied blocks per task id") 277 .flags(nozero | nonan) 278 ; 279 280 percentOccsTaskId 281 .name(name() + ".occ_task_id_percent") 282 .desc("Percentage of cache occupancy per task id") 283 .flags(nozero) 284 ; 285 286 percentOccsTaskId = occupanciesTaskId / Stats::constant(numBlocks); 287 288 tagAccesses 289 .name(name() + ".tag_accesses") 290 .desc("Number of tag accesses") 291 ; 292 293 dataAccesses 294 .name(name() + ".data_accesses") 295 .desc("Number of data accesses") 296 ; 297 298 registerDumpCallback(new BaseTagsDumpCallback(this)); 299 registerExitCallback(new BaseTagsCallback(this)); 300}
|