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"
|
54#include "mem/cache/replacement_policies/replaceable_entry.hh" 55#include "mem/cache/tags/indexing_policies/base.hh" 56#include "mem/request.hh" 57#include "sim/core.hh" 58#include "sim/sim_exit.hh" 59#include "sim/system.hh" 60 61BaseTags::BaseTags(const Params *p) 62 : ClockedObject(p), blkSize(p->block_size), blkMask(blkSize - 1), 63 size(p->size), lookupLatency(p->tag_latency),
|
65 cache(nullptr), indexingPolicy(p->indexing_policy),
|
64 system(p->system), indexingPolicy(p->indexing_policy), |
65 warmupBound((p->warmup_percentage/100.0) * (p->size / p->block_size)), 66 warmedUp(false), numBlocks(p->size / p->block_size), 67 dataBlks(new uint8_t[p->size]) // Allocate data storage in one big chunk 68{ 69} 70
|
72void
73BaseTags::setCache(BaseCache *_cache)
74{
75 assert(!cache);
76 cache = _cache;
77}
78
|
71ReplaceableEntry* 72BaseTags::findBlockBySetAndWay(int set, int way) const 73{ 74 return indexingPolicy->getEntry(set, way); 75} 76 77CacheBlk* 78BaseTags::findBlock(Addr addr, bool is_secure) const 79{ 80 // Extract block tag 81 Addr tag = extractTag(addr); 82 83 // Find possible entries that may contain the given address 84 const std::vector<ReplaceableEntry*> entries = 85 indexingPolicy->getPossibleEntries(addr); 86 87 // Search for block 88 for (const auto& location : entries) { 89 CacheBlk* blk = static_cast<CacheBlk*>(location); 90 if ((blk->tag == tag) && blk->isValid() && 91 (blk->isSecure() == is_secure)) { 92 return blk; 93 } 94 } 95 96 // Did not find block 97 return nullptr; 98} 99 100void 101BaseTags::insertBlock(const Addr addr, const bool is_secure, 102 const int src_master_ID, const uint32_t task_ID, 103 CacheBlk *blk) 104{ 105 assert(!blk->isValid()); 106 107 // Previous block, if existed, has been removed, and now we have 108 // to insert the new one 109 // Deal with what we are bringing in
|
118 assert(src_master_ID < cache->system->maxMasters());
|
110 assert(src_master_ID < system->maxMasters()); |
111 occupancies[src_master_ID]++; 112 113 // Insert block with tag, src master id and task id 114 blk->insert(extractTag(addr), is_secure, src_master_ID, task_ID); 115 116 // Check if cache warm up is done 117 if (!warmedUp && tagsInUse.value() >= warmupBound) { 118 warmedUp = true; 119 warmupCycle = curTick(); 120 } 121 122 // We only need to write into one tag and one data block. 123 tagAccesses += 1; 124 dataAccesses += 1; 125} 126 127Addr 128BaseTags::extractTag(const Addr addr) const 129{ 130 return indexingPolicy->extractTag(addr); 131} 132 133void 134BaseTags::cleanupRefsVisitor(CacheBlk &blk) 135{ 136 if (blk.isValid()) { 137 totalRefs += blk.refCount; 138 ++sampledRefs; 139 } 140} 141 142void 143BaseTags::cleanupRefs() 144{ 145 forEachBlk([this](CacheBlk &blk) { cleanupRefsVisitor(blk); }); 146} 147 148void 149BaseTags::computeStatsVisitor(CacheBlk &blk) 150{ 151 if (blk.isValid()) { 152 assert(blk.task_id < ContextSwitchTaskId::NumTaskId); 153 occupanciesTaskId[blk.task_id]++; 154 assert(blk.tickInserted <= curTick()); 155 Tick age = curTick() - blk.tickInserted; 156 157 int age_index; 158 if (age / SimClock::Int::us < 10) { // <10us 159 age_index = 0; 160 } else if (age / SimClock::Int::us < 100) { // <100us 161 age_index = 1; 162 } else if (age / SimClock::Int::ms < 1) { // <1ms 163 age_index = 2; 164 } else if (age / SimClock::Int::ms < 10) { // <10ms 165 age_index = 3; 166 } else 167 age_index = 4; // >10ms 168 169 ageTaskId[blk.task_id][age_index]++; 170 } 171} 172 173void 174BaseTags::computeStats() 175{ 176 for (unsigned i = 0; i < ContextSwitchTaskId::NumTaskId; ++i) { 177 occupanciesTaskId[i] = 0; 178 for (unsigned j = 0; j < 5; ++j) { 179 ageTaskId[i][j] = 0; 180 } 181 } 182 183 forEachBlk([this](CacheBlk &blk) { computeStatsVisitor(blk); }); 184} 185 186std::string 187BaseTags::print() 188{ 189 std::string str; 190 191 auto print_blk = [&str](CacheBlk &blk) { 192 if (blk.isValid()) 193 str += csprintf("\tBlock: %s\n", blk.print()); 194 }; 195 forEachBlk(print_blk); 196 197 if (str.empty()) 198 str = "no valid tags\n"; 199 200 return str; 201} 202 203void 204BaseTags::regStats() 205{ 206 ClockedObject::regStats(); 207 208 using namespace Stats; 209 210 tagsInUse 211 .name(name() + ".tagsinuse") 212 .desc("Cycle average of tags in use") 213 ; 214 215 totalRefs 216 .name(name() + ".total_refs") 217 .desc("Total number of references to valid blocks.") 218 ; 219 220 sampledRefs 221 .name(name() + ".sampled_refs") 222 .desc("Sample count of references to valid blocks.") 223 ; 224 225 avgRefs 226 .name(name() + ".avg_refs") 227 .desc("Average number of references to valid blocks.") 228 ; 229 230 avgRefs = totalRefs/sampledRefs; 231 232 warmupCycle 233 .name(name() + ".warmup_cycle") 234 .desc("Cycle when the warmup percentage was hit.") 235 ; 236 237 occupancies
|
246 .init(cache->system->maxMasters())
|
238 .init(system->maxMasters()) |
239 .name(name() + ".occ_blocks") 240 .desc("Average occupied blocks per requestor") 241 .flags(nozero | nonan) 242 ;
|
251 for (int i = 0; i < cache->system->maxMasters(); i++) {
252 occupancies.subname(i, cache->system->getMasterName(i));
|
243 for (int i = 0; i < system->maxMasters(); i++) { 244 occupancies.subname(i, system->getMasterName(i)); |
245 } 246 247 avgOccs 248 .name(name() + ".occ_percent") 249 .desc("Average percentage of cache occupancy") 250 .flags(nozero | total) 251 ;
|
260 for (int i = 0; i < cache->system->maxMasters(); i++) {
261 avgOccs.subname(i, cache->system->getMasterName(i));
|
252 for (int i = 0; i < system->maxMasters(); i++) { 253 avgOccs.subname(i, system->getMasterName(i)); |
254 } 255 256 avgOccs = occupancies / Stats::constant(numBlocks); 257 258 occupanciesTaskId 259 .init(ContextSwitchTaskId::NumTaskId) 260 .name(name() + ".occ_task_id_blocks") 261 .desc("Occupied blocks per task id") 262 .flags(nozero | nonan) 263 ; 264 265 ageTaskId 266 .init(ContextSwitchTaskId::NumTaskId, 5) 267 .name(name() + ".age_task_id_blocks") 268 .desc("Occupied blocks per task id") 269 .flags(nozero | nonan) 270 ; 271 272 percentOccsTaskId 273 .name(name() + ".occ_task_id_percent") 274 .desc("Percentage of cache occupancy per task id") 275 .flags(nozero) 276 ; 277 278 percentOccsTaskId = occupanciesTaskId / Stats::constant(numBlocks); 279 280 tagAccesses 281 .name(name() + ".tag_accesses") 282 .desc("Number of tag accesses") 283 ; 284 285 dataAccesses 286 .name(name() + ".data_accesses") 287 .desc("Number of data accesses") 288 ; 289 290 registerDumpCallback(new BaseTagsDumpCallback(this)); 291 registerExitCallback(new BaseTagsCallback(this)); 292}
|