base.cc revision 2858
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, isCpuSide); 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 122 pkt = cachePort->cache->getCoherencePacket(); 123 bool success = cachePort->sendTiming(pkt); 124 cachePort->cache->sendResult(pkt, success); 125 return; 126 } 127 //Know the packet to send, no need to mark in service (must succed) 128 bool success = cachePort->sendTiming(pkt); 129 assert(success); 130} 131 132const char * 133BaseCache::CacheEvent::description() 134{ 135 return "timing event\n"; 136} 137 138Port* 139BaseCache::getPort(const std::string &if_name, int idx) 140{ 141 if (if_name == "") 142 { 143 if(cpuSidePort == NULL) 144 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 145 return cpuSidePort; 146 } 147 else if (if_name == "functional") 148 { 149 if(cpuSidePort == NULL) 150 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 151 return cpuSidePort; 152 } 153 else if (if_name == "cpu_side") 154 { 155 if(cpuSidePort == NULL) 156 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 157 return cpuSidePort; 158 } 159 else if (if_name == "mem_side") 160 { 161 if (memSidePort != NULL) 162 panic("Already have a mem side for this cache\n"); 163 memSidePort = new CachePort(name() + "-mem_side_port", this, false); 164 return memSidePort; 165 } 166 else panic("Port name %s unrecognized\n", if_name); 167} 168 169void 170BaseCache::init() 171{ 172 if (!cpuSidePort || !memSidePort) 173 panic("Cache not hooked up on both sides\n"); 174 cpuSidePort->sendStatusChange(Port::RangeChange); 175} 176 177void 178BaseCache::regStats() 179{ 180 Request temp_req((Addr) NULL, 4, 0); 181 Packet::Command temp_cmd = Packet::ReadReq; 182 Packet temp_pkt(&temp_req, temp_cmd, 0); //@todo FIx command strings so this isn't neccessary 183 temp_pkt.allocate(); //Temp allocate, all need data 184 185 using namespace Stats; 186 187 // Hit statistics 188 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 189 Packet::Command cmd = (Packet::Command)access_idx; 190 const string &cstr = temp_pkt.cmdIdxToString(cmd); 191 192 hits[access_idx] 193 .init(maxThreadsPerCPU) 194 .name(name() + "." + cstr + "_hits") 195 .desc("number of " + cstr + " hits") 196 .flags(total | nozero | nonan) 197 ; 198 } 199 200 demandHits 201 .name(name() + ".demand_hits") 202 .desc("number of demand (read+write) hits") 203 .flags(total) 204 ; 205 demandHits = hits[Packet::ReadReq] + hits[Packet::WriteReq]; 206 207 overallHits 208 .name(name() + ".overall_hits") 209 .desc("number of overall hits") 210 .flags(total) 211 ; 212 overallHits = demandHits + hits[Packet::SoftPFReq] + hits[Packet::HardPFReq] 213 + hits[Packet::Writeback]; 214 215 // Miss statistics 216 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 217 Packet::Command cmd = (Packet::Command)access_idx; 218 const string &cstr = temp_pkt.cmdIdxToString(cmd); 219 220 misses[access_idx] 221 .init(maxThreadsPerCPU) 222 .name(name() + "." + cstr + "_misses") 223 .desc("number of " + cstr + " misses") 224 .flags(total | nozero | nonan) 225 ; 226 } 227 228 demandMisses 229 .name(name() + ".demand_misses") 230 .desc("number of demand (read+write) misses") 231 .flags(total) 232 ; 233 demandMisses = misses[Packet::ReadReq] + misses[Packet::WriteReq]; 234 235 overallMisses 236 .name(name() + ".overall_misses") 237 .desc("number of overall misses") 238 .flags(total) 239 ; 240 overallMisses = demandMisses + misses[Packet::SoftPFReq] + 241 misses[Packet::HardPFReq] + misses[Packet::Writeback]; 242 243 // Miss latency statistics 244 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 245 Packet::Command cmd = (Packet::Command)access_idx; 246 const string &cstr = temp_pkt.cmdIdxToString(cmd); 247 248 missLatency[access_idx] 249 .init(maxThreadsPerCPU) 250 .name(name() + "." + cstr + "_miss_latency") 251 .desc("number of " + cstr + " miss cycles") 252 .flags(total | nozero | nonan) 253 ; 254 } 255 256 demandMissLatency 257 .name(name() + ".demand_miss_latency") 258 .desc("number of demand (read+write) miss cycles") 259 .flags(total) 260 ; 261 demandMissLatency = missLatency[Packet::ReadReq] + missLatency[Packet::WriteReq]; 262 263 overallMissLatency 264 .name(name() + ".overall_miss_latency") 265 .desc("number of overall miss cycles") 266 .flags(total) 267 ; 268 overallMissLatency = demandMissLatency + missLatency[Packet::SoftPFReq] + 269 missLatency[Packet::HardPFReq]; 270 271 // access formulas 272 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 273 Packet::Command cmd = (Packet::Command)access_idx; 274 const string &cstr = temp_pkt.cmdIdxToString(cmd); 275 276 accesses[access_idx] 277 .name(name() + "." + cstr + "_accesses") 278 .desc("number of " + cstr + " accesses(hits+misses)") 279 .flags(total | nozero | nonan) 280 ; 281 282 accesses[access_idx] = hits[access_idx] + misses[access_idx]; 283 } 284 285 demandAccesses 286 .name(name() + ".demand_accesses") 287 .desc("number of demand (read+write) accesses") 288 .flags(total) 289 ; 290 demandAccesses = demandHits + demandMisses; 291 292 overallAccesses 293 .name(name() + ".overall_accesses") 294 .desc("number of overall (read+write) accesses") 295 .flags(total) 296 ; 297 overallAccesses = overallHits + overallMisses; 298 299 // miss rate formulas 300 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 301 Packet::Command cmd = (Packet::Command)access_idx; 302 const string &cstr = temp_pkt.cmdIdxToString(cmd); 303 304 missRate[access_idx] 305 .name(name() + "." + cstr + "_miss_rate") 306 .desc("miss rate for " + cstr + " accesses") 307 .flags(total | nozero | nonan) 308 ; 309 310 missRate[access_idx] = misses[access_idx] / accesses[access_idx]; 311 } 312 313 demandMissRate 314 .name(name() + ".demand_miss_rate") 315 .desc("miss rate for demand accesses") 316 .flags(total) 317 ; 318 demandMissRate = demandMisses / demandAccesses; 319 320 overallMissRate 321 .name(name() + ".overall_miss_rate") 322 .desc("miss rate for overall accesses") 323 .flags(total) 324 ; 325 overallMissRate = overallMisses / overallAccesses; 326 327 // miss latency formulas 328 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 329 Packet::Command cmd = (Packet::Command)access_idx; 330 const string &cstr = temp_pkt.cmdIdxToString(cmd); 331 332 avgMissLatency[access_idx] 333 .name(name() + "." + cstr + "_avg_miss_latency") 334 .desc("average " + cstr + " miss latency") 335 .flags(total | nozero | nonan) 336 ; 337 338 avgMissLatency[access_idx] = 339 missLatency[access_idx] / misses[access_idx]; 340 } 341 342 demandAvgMissLatency 343 .name(name() + ".demand_avg_miss_latency") 344 .desc("average overall miss latency") 345 .flags(total) 346 ; 347 demandAvgMissLatency = demandMissLatency / demandMisses; 348 349 overallAvgMissLatency 350 .name(name() + ".overall_avg_miss_latency") 351 .desc("average overall miss latency") 352 .flags(total) 353 ; 354 overallAvgMissLatency = overallMissLatency / overallMisses; 355 356 blocked_cycles.init(NUM_BLOCKED_CAUSES); 357 blocked_cycles 358 .name(name() + ".blocked_cycles") 359 .desc("number of cycles access was blocked") 360 .subname(Blocked_NoMSHRs, "no_mshrs") 361 .subname(Blocked_NoTargets, "no_targets") 362 ; 363 364 365 blocked_causes.init(NUM_BLOCKED_CAUSES); 366 blocked_causes 367 .name(name() + ".blocked") 368 .desc("number of cycles access was blocked") 369 .subname(Blocked_NoMSHRs, "no_mshrs") 370 .subname(Blocked_NoTargets, "no_targets") 371 ; 372 373 avg_blocked 374 .name(name() + ".avg_blocked_cycles") 375 .desc("average number of cycles each access was blocked") 376 .subname(Blocked_NoMSHRs, "no_mshrs") 377 .subname(Blocked_NoTargets, "no_targets") 378 ; 379 380 avg_blocked = blocked_cycles / blocked_causes; 381 382 fastWrites 383 .name(name() + ".fast_writes") 384 .desc("number of fast writes performed") 385 ; 386 387 cacheCopies 388 .name(name() + ".cache_copies") 389 .desc("number of cache copies performed") 390 ; 391 392} 393