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