base.cc revision 2826
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 101Port* 102BaseCache::getPort(const std::string &if_name, int idx) 103{ 104 if (if_name == "") 105 { 106 if(cpuSidePort == NULL) 107 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 108 return cpuSidePort; 109 } 110 if (if_name == "functional") 111 { 112 if(cpuSidePort == NULL) 113 cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 114 return cpuSidePort; 115 } 116 else if (if_name == "mem_side") 117 { 118 if (memSidePort != NULL) 119 panic("Already have a mem side for this cache\n"); 120 memSidePort = new CachePort(name() + "-mem_side_port", this, false); 121 return memSidePort; 122 } 123 else panic("Port name %s unrecognized\n", if_name); 124} 125 126void 127BaseCache::regStats() 128{ 129 Request temp_req((Addr) NULL, 4, 0); 130 Packet::Command temp_cmd = Packet::ReadReq; 131 Packet temp_pkt(&temp_req, temp_cmd, 0); //@todo FIx command strings so this isn't neccessary 132 temp_pkt.allocate(); //Temp allocate, all need data 133 134 using namespace Stats; 135 136 // Hit statistics 137 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 138 Packet::Command cmd = (Packet::Command)access_idx; 139 const string &cstr = temp_pkt.cmdIdxToString(cmd); 140 141 hits[access_idx] 142 .init(maxThreadsPerCPU) 143 .name(name() + "." + cstr + "_hits") 144 .desc("number of " + cstr + " hits") 145 .flags(total | nozero | nonan) 146 ; 147 } 148 149 demandHits 150 .name(name() + ".demand_hits") 151 .desc("number of demand (read+write) hits") 152 .flags(total) 153 ; 154 demandHits = hits[Packet::ReadReq] + hits[Packet::WriteReq]; 155 156 overallHits 157 .name(name() + ".overall_hits") 158 .desc("number of overall hits") 159 .flags(total) 160 ; 161 overallHits = demandHits + hits[Packet::SoftPFReq] + hits[Packet::HardPFReq] 162 + hits[Packet::Writeback]; 163 164 // Miss statistics 165 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 166 Packet::Command cmd = (Packet::Command)access_idx; 167 const string &cstr = temp_pkt.cmdIdxToString(cmd); 168 169 misses[access_idx] 170 .init(maxThreadsPerCPU) 171 .name(name() + "." + cstr + "_misses") 172 .desc("number of " + cstr + " misses") 173 .flags(total | nozero | nonan) 174 ; 175 } 176 177 demandMisses 178 .name(name() + ".demand_misses") 179 .desc("number of demand (read+write) misses") 180 .flags(total) 181 ; 182 demandMisses = misses[Packet::ReadReq] + misses[Packet::WriteReq]; 183 184 overallMisses 185 .name(name() + ".overall_misses") 186 .desc("number of overall misses") 187 .flags(total) 188 ; 189 overallMisses = demandMisses + misses[Packet::SoftPFReq] + 190 misses[Packet::HardPFReq] + misses[Packet::Writeback]; 191 192 // Miss latency statistics 193 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 194 Packet::Command cmd = (Packet::Command)access_idx; 195 const string &cstr = temp_pkt.cmdIdxToString(cmd); 196 197 missLatency[access_idx] 198 .init(maxThreadsPerCPU) 199 .name(name() + "." + cstr + "_miss_latency") 200 .desc("number of " + cstr + " miss cycles") 201 .flags(total | nozero | nonan) 202 ; 203 } 204 205 demandMissLatency 206 .name(name() + ".demand_miss_latency") 207 .desc("number of demand (read+write) miss cycles") 208 .flags(total) 209 ; 210 demandMissLatency = missLatency[Packet::ReadReq] + missLatency[Packet::WriteReq]; 211 212 overallMissLatency 213 .name(name() + ".overall_miss_latency") 214 .desc("number of overall miss cycles") 215 .flags(total) 216 ; 217 overallMissLatency = demandMissLatency + missLatency[Packet::SoftPFReq] + 218 missLatency[Packet::HardPFReq]; 219 220 // access formulas 221 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 222 Packet::Command cmd = (Packet::Command)access_idx; 223 const string &cstr = temp_pkt.cmdIdxToString(cmd); 224 225 accesses[access_idx] 226 .name(name() + "." + cstr + "_accesses") 227 .desc("number of " + cstr + " accesses(hits+misses)") 228 .flags(total | nozero | nonan) 229 ; 230 231 accesses[access_idx] = hits[access_idx] + misses[access_idx]; 232 } 233 234 demandAccesses 235 .name(name() + ".demand_accesses") 236 .desc("number of demand (read+write) accesses") 237 .flags(total) 238 ; 239 demandAccesses = demandHits + demandMisses; 240 241 overallAccesses 242 .name(name() + ".overall_accesses") 243 .desc("number of overall (read+write) accesses") 244 .flags(total) 245 ; 246 overallAccesses = overallHits + overallMisses; 247 248 // miss rate formulas 249 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 250 Packet::Command cmd = (Packet::Command)access_idx; 251 const string &cstr = temp_pkt.cmdIdxToString(cmd); 252 253 missRate[access_idx] 254 .name(name() + "." + cstr + "_miss_rate") 255 .desc("miss rate for " + cstr + " accesses") 256 .flags(total | nozero | nonan) 257 ; 258 259 missRate[access_idx] = misses[access_idx] / accesses[access_idx]; 260 } 261 262 demandMissRate 263 .name(name() + ".demand_miss_rate") 264 .desc("miss rate for demand accesses") 265 .flags(total) 266 ; 267 demandMissRate = demandMisses / demandAccesses; 268 269 overallMissRate 270 .name(name() + ".overall_miss_rate") 271 .desc("miss rate for overall accesses") 272 .flags(total) 273 ; 274 overallMissRate = overallMisses / overallAccesses; 275 276 // miss latency formulas 277 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 278 Packet::Command cmd = (Packet::Command)access_idx; 279 const string &cstr = temp_pkt.cmdIdxToString(cmd); 280 281 avgMissLatency[access_idx] 282 .name(name() + "." + cstr + "_avg_miss_latency") 283 .desc("average " + cstr + " miss latency") 284 .flags(total | nozero | nonan) 285 ; 286 287 avgMissLatency[access_idx] = 288 missLatency[access_idx] / misses[access_idx]; 289 } 290 291 demandAvgMissLatency 292 .name(name() + ".demand_avg_miss_latency") 293 .desc("average overall miss latency") 294 .flags(total) 295 ; 296 demandAvgMissLatency = demandMissLatency / demandMisses; 297 298 overallAvgMissLatency 299 .name(name() + ".overall_avg_miss_latency") 300 .desc("average overall miss latency") 301 .flags(total) 302 ; 303 overallAvgMissLatency = overallMissLatency / overallMisses; 304 305 blocked_cycles.init(NUM_BLOCKED_CAUSES); 306 blocked_cycles 307 .name(name() + ".blocked_cycles") 308 .desc("number of cycles access was blocked") 309 .subname(Blocked_NoMSHRs, "no_mshrs") 310 .subname(Blocked_NoTargets, "no_targets") 311 ; 312 313 314 blocked_causes.init(NUM_BLOCKED_CAUSES); 315 blocked_causes 316 .name(name() + ".blocked") 317 .desc("number of cycles access was blocked") 318 .subname(Blocked_NoMSHRs, "no_mshrs") 319 .subname(Blocked_NoTargets, "no_targets") 320 ; 321 322 avg_blocked 323 .name(name() + ".avg_blocked_cycles") 324 .desc("average number of cycles each access was blocked") 325 .subname(Blocked_NoMSHRs, "no_mshrs") 326 .subname(Blocked_NoTargets, "no_targets") 327 ; 328 329 avg_blocked = blocked_cycles / blocked_causes; 330 331 fastWrites 332 .name(name() + ".fast_writes") 333 .desc("number of fast writes performed") 334 ; 335 336 cacheCopies 337 .name(name() + ".cache_copies") 338 .desc("number of cache copies performed") 339 ; 340 341} 342