base.cc revision 2897
1848SN/A/* 29956SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan 39956SN/A * All rights reserved. 49956SN/A * 59956SN/A * Redistribution and use in source and binary forms, with or without 69956SN/A * modification, are permitted provided that the following conditions are 79956SN/A * met: redistributions of source code must retain the above copyright 89956SN/A * notice, this list of conditions and the following disclaimer; 99956SN/A * redistributions in binary form must reproduce the above copyright 109956SN/A * notice, this list of conditions and the following disclaimer in the 119956SN/A * documentation and/or other materials provided with the distribution; 129956SN/A * neither the name of the copyright holders nor the names of its 139956SN/A * contributors may be used to endorse or promote products derived from 141762SN/A * this software without specific prior written permission. 15848SN/A * 16848SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17848SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18848SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19848SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20848SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21848SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22848SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23848SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24848SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25848SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26848SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27848SN/A * 28848SN/A * Authors: Erik Hallnor 29848SN/A */ 30848SN/A 31848SN/A/** 32848SN/A * @file 33848SN/A * Definition of BaseCache functions. 34848SN/A */ 35848SN/A 36848SN/A#include "mem/cache/base_cache.hh" 37848SN/A#include "cpu/smt.hh" 38848SN/A#include "cpu/base.hh" 392665SN/A 402665SN/Ausing namespace std; 412665SN/A 42848SN/ABaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache, 43848SN/A bool _isCpuSide) 44848SN/A : Port(_name), cache(_cache), isCpuSide(_isCpuSide) 45848SN/A{ 46848SN/A blocked = false; 47848SN/A //Start ports at null if more than one is created we should panic 4811264Sandreas.sandberg@arm.com //cpuSidePort = NULL; 4911264Sandreas.sandberg@arm.com //memSidePort = NULL; 50848SN/A} 51848SN/A 52848SN/Avoid 53848SN/ABaseCache::CachePort::recvStatusChange(Port::Status status) 54848SN/A{ 554762SN/A cache->recvStatusChange(status, isCpuSide); 562565SN/A} 57848SN/A 58848SN/Avoid 598229SN/ABaseCache::CachePort::getDeviceAddressRanges(AddrRangeList &resp, 608232SN/A AddrRangeList &snoop) 6111264Sandreas.sandberg@arm.com{ 6211264Sandreas.sandberg@arm.com cache->getAddressRanges(resp, snoop, isCpuSide); 634762SN/A} 64848SN/A 65848SN/Aint 66848SN/ABaseCache::CachePort::deviceBlockSize() 672107SN/A{ 68848SN/A return cache->getBlockSize(); 695034SN/A} 705034SN/A 7112087Sspwilson2@wisc.edubool 7212087Sspwilson2@wisc.eduBaseCache::CachePort::recvTiming(Packet *pkt) 7312087Sspwilson2@wisc.edu{ 7412087Sspwilson2@wisc.edu if (blocked) 7512087Sspwilson2@wisc.edu { 7612087Sspwilson2@wisc.edu mustSendRetry = true; 7712087Sspwilson2@wisc.edu return false; 7812087Sspwilson2@wisc.edu } 79848SN/A return cache->doTimingAccess(pkt, this, isCpuSide); 80893SN/A} 815034SN/A 82893SN/ATick 83849SN/ABaseCache::CachePort::recvAtomic(Packet *pkt) 841722SN/A{ 85849SN/A return cache->doAtomicAccess(pkt, isCpuSide); 86849SN/A} 87849SN/A 88849SN/Avoid 89849SN/ABaseCache::CachePort::recvFunctional(Packet *pkt) 90849SN/A{ 91849SN/A cache->doFunctionalAccess(pkt, isCpuSide); 92849SN/A} 93849SN/A 94849SN/Avoid 95849SN/ABaseCache::CachePort::setBlocked() 96849SN/A{ 97849SN/A blocked = true; 98849SN/A} 9911101SN/A 10011101SN/Avoid 101849SN/ABaseCache::CachePort::clearBlocked() 102849SN/A{ 103849SN/A if (mustSendRetry) 104849SN/A { 105849SN/A mustSendRetry = false; 106849SN/A sendRetry(); 107849SN/A } 108849SN/A blocked = false; 109849SN/A} 110849SN/A 111849SN/ABaseCache::CacheEvent::CacheEvent(CachePort *_cachePort) 112849SN/A : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort) 1131853SN/A{ 1141853SN/A this->setFlags(AutoDelete); 115849SN/A pkt = NULL; 1161722SN/A} 117849SN/A 1181722SN/ABaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, Packet *_pkt) 119849SN/A : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort), pkt(_pkt) 1201722SN/A{ 121849SN/A this->setFlags(AutoDelete); 1221722SN/A} 1231722SN/A 1241722SN/Avoid 125849SN/ABaseCache::CacheEvent::process() 1261722SN/A{ 1271722SN/A if (!pkt) 128849SN/A { 1291722SN/A if (!cachePort->isCpuSide) 130849SN/A { 1312989SN/A pkt = cachePort->cache->getPacket(); 132849SN/A bool success = cachePort->sendTiming(pkt); 1331722SN/A DPRINTF(Cache, "Address %x was %s in sending the timing request\n", 134849SN/A pkt->getAddr(), success ? "succesful" : "unsuccesful"); 1351886SN/A cachePort->cache->sendResult(pkt, success); 136849SN/A if (success && cachePort->cache->doMasterRequest()) 1371722SN/A { 1381817SN/A //Still more to issue, rerequest in 1 cycle 1391817SN/A pkt = NULL; 1401817SN/A this->schedule(curTick+1); 141893SN/A } 142893SN/A } 143893SN/A else 144893SN/A { 145893SN/A pkt = cachePort->cache->getCoherencePacket(); 146893SN/A cachePort->sendTiming(pkt); 147893SN/A } 148893SN/A return; 149893SN/A } 150893SN/A //Know the packet to send, no need to mark in service (must succed) 151893SN/A bool success = cachePort->sendTiming(pkt); 152893SN/A assert(success); 153893SN/A} 154893SN/A 155893SN/Aconst char * 156893SN/ABaseCache::CacheEvent::description() 157893SN/A{ 158893SN/A return "timing event\n"; 159893SN/A} 160893SN/A 161893SN/APort* 162893SN/ABaseCache::getPort(const std::string &if_name, int idx) 163893SN/A{ 164893SN/A if (if_name == "") 165893SN/A { 1669956SN/A if(cpuSidePort == NULL) 167849SN/A cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 168849SN/A return cpuSidePort; 169849SN/A } 170849SN/A else if (if_name == "functional") 171849SN/A { 172849SN/A if(cpuSidePort == NULL) 173849SN/A cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 174849SN/A return cpuSidePort; 175849SN/A } 176849SN/A else if (if_name == "cpu_side") 177849SN/A { 178849SN/A if(cpuSidePort == NULL) 179849SN/A cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 180849SN/A return cpuSidePort; 181849SN/A } 182893SN/A else if (if_name == "mem_side") 1831817SN/A { 1841817SN/A if (memSidePort != NULL) 1851817SN/A panic("Already have a mem side for this cache\n"); 1861817SN/A memSidePort = new CachePort(name() + "-mem_side_port", this, false); 187849SN/A return memSidePort; 188849SN/A } 189864SN/A else panic("Port name %s unrecognized\n", if_name); 190864SN/A} 191864SN/A 192864SN/Avoid 193929SN/ABaseCache::init() 194929SN/A{ 195929SN/A if (!cpuSidePort || !memSidePort) 196929SN/A panic("Cache not hooked up on both sides\n"); 197929SN/A cpuSidePort->sendStatusChange(Port::RangeChange); 198929SN/A} 199861SN/A 200864SN/Avoid 201861SN/ABaseCache::regStats() 202861SN/A{ 2035772SN/A Request temp_req((Addr) NULL, 4, 0); 204861SN/A Packet::Command temp_cmd = Packet::ReadReq; 205861SN/A Packet temp_pkt(&temp_req, temp_cmd, 0); //@todo FIx command strings so this isn't neccessary 206861SN/A temp_pkt.allocate(); //Temp allocate, all need data 207861SN/A 208849SN/A using namespace Stats; 209849SN/A 210849SN/A // Hit statistics 211849SN/A for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 212849SN/A Packet::Command cmd = (Packet::Command)access_idx; 2135772SN/A const string &cstr = temp_pkt.cmdIdxToString(cmd); 214849SN/A 2155772SN/A hits[access_idx] 2165772SN/A .init(maxThreadsPerCPU) 2175772SN/A .name(name() + "." + cstr + "_hits") 2185772SN/A .desc("number of " + cstr + " hits") 2195772SN/A .flags(total | nozero | nonan) 2205772SN/A ; 2215772SN/A } 2225772SN/A 2235772SN/A demandHits 2241817SN/A .name(name() + ".demand_hits") 2255772SN/A .desc("number of demand (read+write) hits") 2265772SN/A .flags(total) 2275772SN/A ; 2285772SN/A demandHits = hits[Packet::ReadReq] + hits[Packet::WriteReq]; 2295772SN/A 2305772SN/A overallHits 2315772SN/A .name(name() + ".overall_hits") 2321817SN/A .desc("number of overall hits") 2335772SN/A .flags(total) 2345772SN/A ; 2355772SN/A overallHits = demandHits + hits[Packet::SoftPFReq] + hits[Packet::HardPFReq] 2365772SN/A + hits[Packet::Writeback]; 2375772SN/A 2385772SN/A // Miss statistics 2395772SN/A for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 2405772SN/A Packet::Command cmd = (Packet::Command)access_idx; 2415772SN/A const string &cstr = temp_pkt.cmdIdxToString(cmd); 2425772SN/A 2435772SN/A misses[access_idx] 2445772SN/A .init(maxThreadsPerCPU) 2455772SN/A .name(name() + "." + cstr + "_misses") 2465772SN/A .desc("number of " + cstr + " misses") 2475772SN/A .flags(total | nozero | nonan) 2485772SN/A ; 2495772SN/A } 2505772SN/A 2511817SN/A demandMisses 2521817SN/A .name(name() + ".demand_misses") 2535772SN/A .desc("number of demand (read+write) misses") 254849SN/A .flags(total) 2555772SN/A ; 256849SN/A demandMisses = misses[Packet::ReadReq] + misses[Packet::WriteReq]; 257849SN/A 258849SN/A overallMisses 2595772SN/A .name(name() + ".overall_misses") 260849SN/A .desc("number of overall misses") 2615772SN/A .flags(total) 2625772SN/A ; 2635772SN/A overallMisses = demandMisses + misses[Packet::SoftPFReq] + 2645772SN/A misses[Packet::HardPFReq] + misses[Packet::Writeback]; 2655772SN/A 2665772SN/A // Miss latency statistics 267849SN/A for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 2685772SN/A Packet::Command cmd = (Packet::Command)access_idx; 2695772SN/A const string &cstr = temp_pkt.cmdIdxToString(cmd); 2705772SN/A 2715772SN/A missLatency[access_idx] 2725772SN/A .init(maxThreadsPerCPU) 2735772SN/A .name(name() + "." + cstr + "_miss_latency") 2745772SN/A .desc("number of " + cstr + " miss cycles") 2755772SN/A .flags(total | nozero | nonan) 2765772SN/A ; 2775772SN/A } 2785772SN/A 2795772SN/A demandMissLatency 2801817SN/A .name(name() + ".demand_miss_latency") 2815772SN/A .desc("number of demand (read+write) miss cycles") 2825772SN/A .flags(total) 2835772SN/A ; 2845772SN/A demandMissLatency = missLatency[Packet::ReadReq] + missLatency[Packet::WriteReq]; 2855772SN/A 2865772SN/A overallMissLatency 2875772SN/A .name(name() + ".overall_miss_latency") 2881817SN/A .desc("number of overall miss cycles") 2895772SN/A .flags(total) 2905772SN/A ; 2915772SN/A overallMissLatency = demandMissLatency + missLatency[Packet::SoftPFReq] + 2925772SN/A missLatency[Packet::HardPFReq]; 2935772SN/A 2945772SN/A // access formulas 2955772SN/A for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 2965772SN/A Packet::Command cmd = (Packet::Command)access_idx; 2975772SN/A const string &cstr = temp_pkt.cmdIdxToString(cmd); 2985772SN/A 2995772SN/A accesses[access_idx] 3005772SN/A .name(name() + "." + cstr + "_accesses") 3015772SN/A .desc("number of " + cstr + " accesses(hits+misses)") 3025772SN/A .flags(total | nozero | nonan) 3035772SN/A ; 3045772SN/A 3055772SN/A accesses[access_idx] = hits[access_idx] + misses[access_idx]; 3065772SN/A } 3075772SN/A 3081817SN/A demandAccesses 3091817SN/A .name(name() + ".demand_accesses") 3105772SN/A .desc("number of demand (read+write) accesses") 311849SN/A .flags(total) 3125772SN/A ; 3135772SN/A demandAccesses = demandHits + demandMisses; 3145772SN/A 3155772SN/A overallAccesses 3165772SN/A .name(name() + ".overall_accesses") 3175772SN/A .desc("number of overall (read+write) accesses") 3185772SN/A .flags(total) 3195772SN/A ; 3205772SN/A overallAccesses = overallHits + overallMisses; 3215772SN/A 3225772SN/A // miss rate formulas 3235772SN/A for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 3245772SN/A Packet::Command cmd = (Packet::Command)access_idx; 3255772SN/A const string &cstr = temp_pkt.cmdIdxToString(cmd); 3265772SN/A 3275772SN/A missRate[access_idx] 3285772SN/A .name(name() + "." + cstr + "_miss_rate") 3295772SN/A .desc("miss rate for " + cstr + " accesses") 3305772SN/A .flags(total | nozero | nonan) 331849SN/A ; 3322566SN/A 3332566SN/A missRate[access_idx] = misses[access_idx] / accesses[access_idx]; 334849SN/A } 335849SN/A 336849SN/A demandMissRate 337849SN/A .name(name() + ".demand_miss_rate") 338849SN/A .desc("miss rate for demand accesses") 339849SN/A .flags(total) 340849SN/A ; 341849SN/A demandMissRate = demandMisses / demandAccesses; 342849SN/A 3439956SN/A overallMissRate 3449956SN/A .name(name() + ".overall_miss_rate") 3459956SN/A .desc("miss rate for overall accesses") 3469956SN/A .flags(total) 3479956SN/A ; 3489956SN/A overallMissRate = overallMisses / overallAccesses; 349849SN/A 350849SN/A // miss latency formulas 351849SN/A for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 352849SN/A Packet::Command cmd = (Packet::Command)access_idx; 35310913SN/A const string &cstr = temp_pkt.cmdIdxToString(cmd); 3547823SN/A 3552565SN/A avgMissLatency[access_idx] 3562565SN/A .name(name() + "." + cstr + "_avg_miss_latency") 3572565SN/A .desc("average " + cstr + " miss latency") 3582565SN/A .flags(total | nozero | nonan) 359849SN/A ; 360849SN/A 361849SN/A avgMissLatency[access_idx] = 362849SN/A missLatency[access_idx] / misses[access_idx]; 363849SN/A } 3649956SN/A 3659956SN/A demandAvgMissLatency 3669956SN/A .name(name() + ".demand_avg_miss_latency") 3679956SN/A .desc("average overall miss latency") 3689956SN/A .flags(total) 3698522SN/A ; 3701625SN/A demandAvgMissLatency = demandMissLatency / demandMisses; 3711625SN/A 372896SN/A overallAvgMissLatency 373896SN/A .name(name() + ".overall_avg_miss_latency") 374896SN/A .desc("average overall miss latency") 375896SN/A .flags(total) 376989SN/A ; 377989SN/A overallAvgMissLatency = overallMissLatency / overallMisses; 378849SN/A 379849SN/A blocked_cycles.init(NUM_BLOCKED_CAUSES); 3802565SN/A blocked_cycles 381849SN/A .name(name() + ".blocked_cycles") 3822565SN/A .desc("number of cycles access was blocked") 383849SN/A .subname(Blocked_NoMSHRs, "no_mshrs") 384849SN/A .subname(Blocked_NoTargets, "no_targets") 385849SN/A ; 3862565SN/A 387849SN/A 3881763SN/A blocked_causes.init(NUM_BLOCKED_CAUSES); 389864SN/A blocked_causes 390849SN/A .name(name() + ".blocked") 3911634SN/A .desc("number of cycles access was blocked") 3921634SN/A .subname(Blocked_NoMSHRs, "no_mshrs") 393849SN/A .subname(Blocked_NoTargets, "no_targets") 3947823SN/A ; 3952565SN/A 396864SN/A avg_blocked 3972627SN/A .name(name() + ".avg_blocked_cycles") 3982627SN/A .desc("average number of cycles each access was blocked") 3992627SN/A .subname(Blocked_NoMSHRs, "no_mshrs") 40011522Sstephan.diestelhorst@arm.com .subname(Blocked_NoTargets, "no_targets") 40111522Sstephan.diestelhorst@arm.com ; 4022627SN/A 4032627SN/A avg_blocked = blocked_cycles / blocked_causes; 4042627SN/A 4052627SN/A fastWrites 4062627SN/A .name(name() + ".fast_writes") 4072627SN/A .desc("number of fast writes performed") 4082627SN/A ; 4092627SN/A 4102627SN/A cacheCopies 4112627SN/A .name(name() + ".cache_copies") 4122627SN/A .desc("number of cache copies performed") 4132627SN/A ; 4142627SN/A 4152627SN/A} 4162627SN/A