base.cc revision 2844
1/* 2 * Copyright (c) 2003-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Erik Hallnor 29 */ 30 31/** 32 * @file 33 * Definition of BaseCache functions. 34 */ 35 36#include "mem/cache/base_cache.hh" 37#include "cpu/smt.hh" 38#include "cpu/base.hh" 39 40using namespace std; 41 42BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache, 43 bool _isCpuSide) 44 : Port(_name), cache(_cache), isCpuSide(_isCpuSide) 45{ 46 blocked = false; 47 //Start ports at null if more than one is created we should panic 48 //cpuSidePort = NULL; 49 //memSidePort = NULL; 50} 51 52void 53BaseCache::CachePort::recvStatusChange(Port::Status status) 54{ 55 cache->recvStatusChange(status, isCpuSide); 56} 57 58void 59BaseCache::CachePort::getDeviceAddressRanges(AddrRangeList &resp, 60 AddrRangeList &snoop) 61{ 62 cache->getAddressRanges(resp, snoop); 63} 64 65int 66BaseCache::CachePort::deviceBlockSize() 67{ 68 return cache->getBlockSize(); 69} 70 71bool 72BaseCache::CachePort::recvTiming(Packet *pkt) 73{ 74 return cache->doTimingAccess(pkt, this, isCpuSide); 75} 76 77Tick 78BaseCache::CachePort::recvAtomic(Packet *pkt) 79{ 80 return cache->doAtomicAccess(pkt, isCpuSide); 81} 82 83void 84BaseCache::CachePort::recvFunctional(Packet *pkt) 85{ 86 cache->doFunctionalAccess(pkt, isCpuSide); 87} 88 89void 90BaseCache::CachePort::setBlocked() 91{ 92 blocked = true; 93} 94 95void 96BaseCache::CachePort::clearBlocked() 97{ 98 blocked = false; 99} 100 101BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort) 102 : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort) 103{ 104 this->setFlags(AutoDelete); 105 pkt = NULL; 106} 107 108BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, Packet *_pkt) 109 : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort), pkt(_pkt) 110{ 111 this->setFlags(AutoDelete); 112} 113 114void 115BaseCache::CacheEvent::process() 116{ 117 if (!pkt) 118 { 119 if (!cachePort->isCpuSide) 120 pkt = cachePort->cache->getPacket(); 121 //Else get coherence req 122 } 123 cachePort->sendTiming(pkt); 124} 125 126const char * 127BaseCache::CacheEvent::description() 128{ 129 return "timing event\n"; 130} 131 132Port* 133BaseCache::getPort(const std::string &if_name, int idx) 134{ 135 if (if_name == "") 136 { 137 if(cpuSidePort == NULL) 138 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 139 return cpuSidePort; 140 } 141 if (if_name == "functional") 142 { 143 if(cpuSidePort == NULL) 144 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 145 return cpuSidePort; 146 } 147 else if (if_name == "mem_side") 148 { 149 if (memSidePort != NULL) 150 panic("Already have a mem side for this cache\n"); 151 memSidePort = new CachePort(name() + "-mem_side_port", this, false); 152 return memSidePort; 153 } 154 else panic("Port name %s unrecognized\n", if_name); 155} 156 157void 158BaseCache::regStats() 159{ 160 Request temp_req((Addr) NULL, 4, 0); 161 Packet::Command temp_cmd = Packet::ReadReq; 162 Packet temp_pkt(&temp_req, temp_cmd, 0); //@todo FIx command strings so this isn't neccessary 163 temp_pkt.allocate(); //Temp allocate, all need data 164 165 using namespace Stats; 166 167 // Hit statistics 168 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 169 Packet::Command cmd = (Packet::Command)access_idx; 170 const string &cstr = temp_pkt.cmdIdxToString(cmd); 171 172 hits[access_idx] 173 .init(maxThreadsPerCPU) 174 .name(name() + "." + cstr + "_hits") 175 .desc("number of " + cstr + " hits") 176 .flags(total | nozero | nonan) 177 ; 178 } 179 180 demandHits 181 .name(name() + ".demand_hits") 182 .desc("number of demand (read+write) hits") 183 .flags(total) 184 ; 185 demandHits = hits[Packet::ReadReq] + hits[Packet::WriteReq]; 186 187 overallHits 188 .name(name() + ".overall_hits") 189 .desc("number of overall hits") 190 .flags(total) 191 ; 192 overallHits = demandHits + hits[Packet::SoftPFReq] + hits[Packet::HardPFReq] 193 + hits[Packet::Writeback]; 194 195 // Miss statistics 196 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 197 Packet::Command cmd = (Packet::Command)access_idx; 198 const string &cstr = temp_pkt.cmdIdxToString(cmd); 199 200 misses[access_idx] 201 .init(maxThreadsPerCPU) 202 .name(name() + "." + cstr + "_misses") 203 .desc("number of " + cstr + " misses") 204 .flags(total | nozero | nonan) 205 ; 206 } 207 208 demandMisses 209 .name(name() + ".demand_misses") 210 .desc("number of demand (read+write) misses") 211 .flags(total) 212 ; 213 demandMisses = misses[Packet::ReadReq] + misses[Packet::WriteReq]; 214 215 overallMisses 216 .name(name() + ".overall_misses") 217 .desc("number of overall misses") 218 .flags(total) 219 ; 220 overallMisses = demandMisses + misses[Packet::SoftPFReq] + 221 misses[Packet::HardPFReq] + misses[Packet::Writeback]; 222 223 // Miss latency statistics 224 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 225 Packet::Command cmd = (Packet::Command)access_idx; 226 const string &cstr = temp_pkt.cmdIdxToString(cmd); 227 228 missLatency[access_idx] 229 .init(maxThreadsPerCPU) 230 .name(name() + "." + cstr + "_miss_latency") 231 .desc("number of " + cstr + " miss cycles") 232 .flags(total | nozero | nonan) 233 ; 234 } 235 236 demandMissLatency 237 .name(name() + ".demand_miss_latency") 238 .desc("number of demand (read+write) miss cycles") 239 .flags(total) 240 ; 241 demandMissLatency = missLatency[Packet::ReadReq] + missLatency[Packet::WriteReq]; 242 243 overallMissLatency 244 .name(name() + ".overall_miss_latency") 245 .desc("number of overall miss cycles") 246 .flags(total) 247 ; 248 overallMissLatency = demandMissLatency + missLatency[Packet::SoftPFReq] + 249 missLatency[Packet::HardPFReq]; 250 251 // access formulas 252 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 253 Packet::Command cmd = (Packet::Command)access_idx; 254 const string &cstr = temp_pkt.cmdIdxToString(cmd); 255 256 accesses[access_idx] 257 .name(name() + "." + cstr + "_accesses") 258 .desc("number of " + cstr + " accesses(hits+misses)") 259 .flags(total | nozero | nonan) 260 ; 261 262 accesses[access_idx] = hits[access_idx] + misses[access_idx]; 263 } 264 265 demandAccesses 266 .name(name() + ".demand_accesses") 267 .desc("number of demand (read+write) accesses") 268 .flags(total) 269 ; 270 demandAccesses = demandHits + demandMisses; 271 272 overallAccesses 273 .name(name() + ".overall_accesses") 274 .desc("number of overall (read+write) accesses") 275 .flags(total) 276 ; 277 overallAccesses = overallHits + overallMisses; 278 279 // miss rate formulas 280 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 281 Packet::Command cmd = (Packet::Command)access_idx; 282 const string &cstr = temp_pkt.cmdIdxToString(cmd); 283 284 missRate[access_idx] 285 .name(name() + "." + cstr + "_miss_rate") 286 .desc("miss rate for " + cstr + " accesses") 287 .flags(total | nozero | nonan) 288 ; 289 290 missRate[access_idx] = misses[access_idx] / accesses[access_idx]; 291 } 292 293 demandMissRate 294 .name(name() + ".demand_miss_rate") 295 .desc("miss rate for demand accesses") 296 .flags(total) 297 ; 298 demandMissRate = demandMisses / demandAccesses; 299 300 overallMissRate 301 .name(name() + ".overall_miss_rate") 302 .desc("miss rate for overall accesses") 303 .flags(total) 304 ; 305 overallMissRate = overallMisses / overallAccesses; 306 307 // miss latency formulas 308 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 309 Packet::Command cmd = (Packet::Command)access_idx; 310 const string &cstr = temp_pkt.cmdIdxToString(cmd); 311 312 avgMissLatency[access_idx] 313 .name(name() + "." + cstr + "_avg_miss_latency") 314 .desc("average " + cstr + " miss latency") 315 .flags(total | nozero | nonan) 316 ; 317 318 avgMissLatency[access_idx] = 319 missLatency[access_idx] / misses[access_idx]; 320 } 321 322 demandAvgMissLatency 323 .name(name() + ".demand_avg_miss_latency") 324 .desc("average overall miss latency") 325 .flags(total) 326 ; 327 demandAvgMissLatency = demandMissLatency / demandMisses; 328 329 overallAvgMissLatency 330 .name(name() + ".overall_avg_miss_latency") 331 .desc("average overall miss latency") 332 .flags(total) 333 ; 334 overallAvgMissLatency = overallMissLatency / overallMisses; 335 336 blocked_cycles.init(NUM_BLOCKED_CAUSES); 337 blocked_cycles 338 .name(name() + ".blocked_cycles") 339 .desc("number of cycles access was blocked") 340 .subname(Blocked_NoMSHRs, "no_mshrs") 341 .subname(Blocked_NoTargets, "no_targets") 342 ; 343 344 345 blocked_causes.init(NUM_BLOCKED_CAUSES); 346 blocked_causes 347 .name(name() + ".blocked") 348 .desc("number of cycles access was blocked") 349 .subname(Blocked_NoMSHRs, "no_mshrs") 350 .subname(Blocked_NoTargets, "no_targets") 351 ; 352 353 avg_blocked 354 .name(name() + ".avg_blocked_cycles") 355 .desc("average number of cycles each access was blocked") 356 .subname(Blocked_NoMSHRs, "no_mshrs") 357 .subname(Blocked_NoTargets, "no_targets") 358 ; 359 360 avg_blocked = blocked_cycles / blocked_causes; 361 362 fastWrites 363 .name(name() + ".fast_writes") 364 .desc("number of fast writes performed") 365 ; 366 367 cacheCopies 368 .name(name() + ".cache_copies") 369 .desc("number of cache copies performed") 370 ; 371 372} 373