base.cc revision 13219:454ecc63338d
114039Sstacze01@arm.com/* 214039Sstacze01@arm.com * Copyright (c) 2013,2016,2018 ARM Limited 314039Sstacze01@arm.com * All rights reserved. 414039Sstacze01@arm.com * 514039Sstacze01@arm.com * The license below extends only to copyright in the software and shall 614039Sstacze01@arm.com * not be construed as granting a license to any other intellectual 714039Sstacze01@arm.com * property including but not limited to intellectual property relating 814039Sstacze01@arm.com * to a hardware implementation of the functionality of the software 914039Sstacze01@arm.com * licensed hereunder. You may use the software subject to the license 1014039Sstacze01@arm.com * terms below provided that you ensure that this notice is replicated 1114039Sstacze01@arm.com * unmodified and in its entirety in all distributions of the software, 1214039Sstacze01@arm.com * modified or unmodified, in source code or in binary form. 1314039Sstacze01@arm.com * 1414039Sstacze01@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 1514039Sstacze01@arm.com * All rights reserved. 1614039Sstacze01@arm.com * 1714039Sstacze01@arm.com * Redistribution and use in source and binary forms, with or without 1814039Sstacze01@arm.com * modification, are permitted provided that the following conditions are 1914039Sstacze01@arm.com * met: redistributions of source code must retain the above copyright 2014039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer; 2114039Sstacze01@arm.com * redistributions in binary form must reproduce the above copyright 2214039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer in the 2314039Sstacze01@arm.com * documentation and/or other materials provided with the distribution; 2414039Sstacze01@arm.com * neither the name of the copyright holders nor the names of its 2514039Sstacze01@arm.com * contributors may be used to endorse or promote products derived from 2614039Sstacze01@arm.com * this software without specific prior written permission. 2714039Sstacze01@arm.com * 2814039Sstacze01@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2914039Sstacze01@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3014039Sstacze01@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3114039Sstacze01@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3214039Sstacze01@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3314039Sstacze01@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3414039Sstacze01@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3514039Sstacze01@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3614039Sstacze01@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3714039Sstacze01@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3814039Sstacze01@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3914039Sstacze01@arm.com * 4014039Sstacze01@arm.com * Authors: Erik Hallnor 4114039Sstacze01@arm.com * Ron Dreslinski 4214039Sstacze01@arm.com */ 4314039Sstacze01@arm.com 4414039Sstacze01@arm.com/** 4514039Sstacze01@arm.com * @file 4614039Sstacze01@arm.com * Definitions of BaseTags. 4714039Sstacze01@arm.com */ 4814039Sstacze01@arm.com 4914039Sstacze01@arm.com#include "mem/cache/tags/base.hh" 5014039Sstacze01@arm.com 5114039Sstacze01@arm.com#include <cassert> 5214039Sstacze01@arm.com 5314039Sstacze01@arm.com#include "base/types.hh" 5414039Sstacze01@arm.com#include "mem/cache/base.hh" 5514039Sstacze01@arm.com#include "mem/cache/tags/indexing_policies/base.hh" 5614039Sstacze01@arm.com#include "mem/request.hh" 5714039Sstacze01@arm.com#include "sim/core.hh" 5814039Sstacze01@arm.com#include "sim/sim_exit.hh" 5914039Sstacze01@arm.com#include "sim/system.hh" 6014039Sstacze01@arm.com 6114039Sstacze01@arm.comBaseTags::BaseTags(const Params *p) 6214039Sstacze01@arm.com : ClockedObject(p), blkSize(p->block_size), blkMask(blkSize - 1), 6314039Sstacze01@arm.com size(p->size), 6414039Sstacze01@arm.com lookupLatency(p->tag_latency), 6514039Sstacze01@arm.com accessLatency(p->sequential_access ? 6614039Sstacze01@arm.com p->tag_latency + p->data_latency : 6714039Sstacze01@arm.com std::max(p->tag_latency, p->data_latency)), 6814039Sstacze01@arm.com cache(nullptr), indexingPolicy(p->indexing_policy), 6914039Sstacze01@arm.com warmupBound((p->warmup_percentage/100.0) * (p->size / p->block_size)), 7014039Sstacze01@arm.com warmedUp(false), numBlocks(p->size / p->block_size), 7114039Sstacze01@arm.com dataBlks(new uint8_t[p->size]) // Allocate data storage in one big chunk 7214039Sstacze01@arm.com{ 7314039Sstacze01@arm.com} 7414039Sstacze01@arm.com 7514039Sstacze01@arm.comvoid 7614039Sstacze01@arm.comBaseTags::setCache(BaseCache *_cache) 7714039Sstacze01@arm.com{ 7814039Sstacze01@arm.com assert(!cache); 7914039Sstacze01@arm.com cache = _cache; 8014039Sstacze01@arm.com} 8114039Sstacze01@arm.com 8214039Sstacze01@arm.comReplaceableEntry* 8314039Sstacze01@arm.comBaseTags::findBlockBySetAndWay(int set, int way) const 8414039Sstacze01@arm.com{ 8514039Sstacze01@arm.com return indexingPolicy->getEntry(set, way); 8614039Sstacze01@arm.com} 8714039Sstacze01@arm.com 8814039Sstacze01@arm.comCacheBlk* 8914039Sstacze01@arm.comBaseTags::findBlock(Addr addr, bool is_secure) const 9014039Sstacze01@arm.com{ 9114039Sstacze01@arm.com // Extract block tag 9214039Sstacze01@arm.com Addr tag = extractTag(addr); 9314039Sstacze01@arm.com 9414039Sstacze01@arm.com // Find possible entries that may contain the given address 9514039Sstacze01@arm.com const std::vector<ReplaceableEntry*> entries = 9614039Sstacze01@arm.com indexingPolicy->getPossibleEntries(addr); 9714039Sstacze01@arm.com 9814039Sstacze01@arm.com // Search for block 9914039Sstacze01@arm.com for (const auto& location : entries) { 10014039Sstacze01@arm.com CacheBlk* blk = static_cast<CacheBlk*>(location); 10114039Sstacze01@arm.com if ((blk->tag == tag) && blk->isValid() && 10214039Sstacze01@arm.com (blk->isSecure() == is_secure)) { 10314039Sstacze01@arm.com return blk; 10414039Sstacze01@arm.com } 10514039Sstacze01@arm.com } 10614039Sstacze01@arm.com 10714039Sstacze01@arm.com // Did not find block 10814039Sstacze01@arm.com return nullptr; 10914039Sstacze01@arm.com} 11014039Sstacze01@arm.com 11114039Sstacze01@arm.comvoid 11214039Sstacze01@arm.comBaseTags::insertBlock(const Addr addr, const bool is_secure, 11314039Sstacze01@arm.com const int src_master_ID, const uint32_t task_ID, 11414039Sstacze01@arm.com CacheBlk *blk) 11514039Sstacze01@arm.com{ 11614039Sstacze01@arm.com assert(!blk->isValid()); 11714039Sstacze01@arm.com 11814039Sstacze01@arm.com // Previous block, if existed, has been removed, and now we have 11914039Sstacze01@arm.com // to insert the new one 12014039Sstacze01@arm.com // Deal with what we are bringing in 12114039Sstacze01@arm.com assert(src_master_ID < cache->system->maxMasters()); 12214039Sstacze01@arm.com occupancies[src_master_ID]++; 12314039Sstacze01@arm.com 12414039Sstacze01@arm.com // Insert block with tag, src master id and task id 12514039Sstacze01@arm.com blk->insert(extractTag(addr), is_secure, src_master_ID, task_ID); 12614039Sstacze01@arm.com 12714039Sstacze01@arm.com // Check if cache warm up is done 12814039Sstacze01@arm.com if (!warmedUp && tagsInUse.value() >= warmupBound) { 12914039Sstacze01@arm.com warmedUp = true; 13014039Sstacze01@arm.com warmupCycle = curTick(); 13114039Sstacze01@arm.com } 13214039Sstacze01@arm.com 13314039Sstacze01@arm.com // We only need to write into one tag and one data block. 13414039Sstacze01@arm.com tagAccesses += 1; 13514039Sstacze01@arm.com dataAccesses += 1; 13614039Sstacze01@arm.com} 13714039Sstacze01@arm.com 13814039Sstacze01@arm.comAddr 13914039Sstacze01@arm.comBaseTags::extractTag(const Addr addr) const 14014039Sstacze01@arm.com{ 14114039Sstacze01@arm.com return indexingPolicy->extractTag(addr); 14214039Sstacze01@arm.com} 14314039Sstacze01@arm.com 14414039Sstacze01@arm.comvoid 14514039Sstacze01@arm.comBaseTags::cleanupRefsVisitor(CacheBlk &blk) 14614039Sstacze01@arm.com{ 14714039Sstacze01@arm.com if (blk.isValid()) { 14814039Sstacze01@arm.com totalRefs += blk.refCount; 14914039Sstacze01@arm.com ++sampledRefs; 15014039Sstacze01@arm.com } 15114039Sstacze01@arm.com} 15214039Sstacze01@arm.com 15314039Sstacze01@arm.comvoid 15414039Sstacze01@arm.comBaseTags::cleanupRefs() 15514039Sstacze01@arm.com{ 15614039Sstacze01@arm.com forEachBlk([this](CacheBlk &blk) { cleanupRefsVisitor(blk); }); 15714039Sstacze01@arm.com} 15814039Sstacze01@arm.com 15914039Sstacze01@arm.comvoid 16014039Sstacze01@arm.comBaseTags::computeStatsVisitor(CacheBlk &blk) 16114039Sstacze01@arm.com{ 16214039Sstacze01@arm.com if (blk.isValid()) { 16314039Sstacze01@arm.com assert(blk.task_id < ContextSwitchTaskId::NumTaskId); 16414039Sstacze01@arm.com occupanciesTaskId[blk.task_id]++; 16514039Sstacze01@arm.com assert(blk.tickInserted <= curTick()); 16614039Sstacze01@arm.com Tick age = curTick() - blk.tickInserted; 16714039Sstacze01@arm.com 16814039Sstacze01@arm.com int age_index; 16914039Sstacze01@arm.com if (age / SimClock::Int::us < 10) { // <10us 17014039Sstacze01@arm.com age_index = 0; 17114039Sstacze01@arm.com } else if (age / SimClock::Int::us < 100) { // <100us 17214039Sstacze01@arm.com age_index = 1; 17314039Sstacze01@arm.com } else if (age / SimClock::Int::ms < 1) { // <1ms 17414039Sstacze01@arm.com age_index = 2; 17514039Sstacze01@arm.com } else if (age / SimClock::Int::ms < 10) { // <10ms 17614039Sstacze01@arm.com age_index = 3; 17714039Sstacze01@arm.com } else 17814039Sstacze01@arm.com age_index = 4; // >10ms 17914039Sstacze01@arm.com 18014039Sstacze01@arm.com ageTaskId[blk.task_id][age_index]++; 18114039Sstacze01@arm.com } 18214039Sstacze01@arm.com} 18314039Sstacze01@arm.com 18414039Sstacze01@arm.comvoid 18514039Sstacze01@arm.comBaseTags::computeStats() 18614039Sstacze01@arm.com{ 18714039Sstacze01@arm.com for (unsigned i = 0; i < ContextSwitchTaskId::NumTaskId; ++i) { 18814039Sstacze01@arm.com occupanciesTaskId[i] = 0; 18914039Sstacze01@arm.com for (unsigned j = 0; j < 5; ++j) { 19014039Sstacze01@arm.com ageTaskId[i][j] = 0; 19114039Sstacze01@arm.com } 19214039Sstacze01@arm.com } 19314039Sstacze01@arm.com 19414039Sstacze01@arm.com forEachBlk([this](CacheBlk &blk) { computeStatsVisitor(blk); }); 19514039Sstacze01@arm.com} 19614039Sstacze01@arm.com 19714039Sstacze01@arm.comstd::string 19814039Sstacze01@arm.comBaseTags::print() 19914039Sstacze01@arm.com{ 20014039Sstacze01@arm.com std::string str; 20114039Sstacze01@arm.com 20214039Sstacze01@arm.com auto print_blk = [&str](CacheBlk &blk) { 20314039Sstacze01@arm.com if (blk.isValid()) 20414039Sstacze01@arm.com str += csprintf("\tset: %x, way: %x %s\n", blk.getSet(), 20514039Sstacze01@arm.com blk.getWay(), blk.print()); 20614039Sstacze01@arm.com }; 20714039Sstacze01@arm.com forEachBlk(print_blk); 20814039Sstacze01@arm.com 20914039Sstacze01@arm.com if (str.empty()) 210 str = "no valid tags\n"; 211 212 return str; 213} 214 215void 216BaseTags::regStats() 217{ 218 ClockedObject::regStats(); 219 220 using namespace Stats; 221 222 tagsInUse 223 .name(name() + ".tagsinuse") 224 .desc("Cycle average of tags in use") 225 ; 226 227 totalRefs 228 .name(name() + ".total_refs") 229 .desc("Total number of references to valid blocks.") 230 ; 231 232 sampledRefs 233 .name(name() + ".sampled_refs") 234 .desc("Sample count of references to valid blocks.") 235 ; 236 237 avgRefs 238 .name(name() + ".avg_refs") 239 .desc("Average number of references to valid blocks.") 240 ; 241 242 avgRefs = totalRefs/sampledRefs; 243 244 warmupCycle 245 .name(name() + ".warmup_cycle") 246 .desc("Cycle when the warmup percentage was hit.") 247 ; 248 249 occupancies 250 .init(cache->system->maxMasters()) 251 .name(name() + ".occ_blocks") 252 .desc("Average occupied blocks per requestor") 253 .flags(nozero | nonan) 254 ; 255 for (int i = 0; i < cache->system->maxMasters(); i++) { 256 occupancies.subname(i, cache->system->getMasterName(i)); 257 } 258 259 avgOccs 260 .name(name() + ".occ_percent") 261 .desc("Average percentage of cache occupancy") 262 .flags(nozero | total) 263 ; 264 for (int i = 0; i < cache->system->maxMasters(); i++) { 265 avgOccs.subname(i, cache->system->getMasterName(i)); 266 } 267 268 avgOccs = occupancies / Stats::constant(numBlocks); 269 270 occupanciesTaskId 271 .init(ContextSwitchTaskId::NumTaskId) 272 .name(name() + ".occ_task_id_blocks") 273 .desc("Occupied blocks per task id") 274 .flags(nozero | nonan) 275 ; 276 277 ageTaskId 278 .init(ContextSwitchTaskId::NumTaskId, 5) 279 .name(name() + ".age_task_id_blocks") 280 .desc("Occupied blocks per task id") 281 .flags(nozero | nonan) 282 ; 283 284 percentOccsTaskId 285 .name(name() + ".occ_task_id_percent") 286 .desc("Percentage of cache occupancy per task id") 287 .flags(nozero) 288 ; 289 290 percentOccsTaskId = occupanciesTaskId / Stats::constant(numBlocks); 291 292 tagAccesses 293 .name(name() + ".tag_accesses") 294 .desc("Number of tag accesses") 295 ; 296 297 dataAccesses 298 .name(name() + ".data_accesses") 299 .desc("Number of data accesses") 300 ; 301 302 registerDumpCallback(new BaseTagsDumpCallback(this)); 303 registerExitCallback(new BaseTagsCallback(this)); 304} 305