base.cc revision 10061
114039Sstacze01@arm.com/*
214039Sstacze01@arm.com * Copyright (c) 2010-2012 ARM Limited
314039Sstacze01@arm.com * Copyright (c) 2013 Advanced Micro Devices, Inc.
414039Sstacze01@arm.com * All rights reserved
514039Sstacze01@arm.com *
614039Sstacze01@arm.com * The license below extends only to copyright in the software and shall
714039Sstacze01@arm.com * not be construed as granting a license to any other intellectual
814039Sstacze01@arm.com * property including but not limited to intellectual property relating
914039Sstacze01@arm.com * to a hardware implementation of the functionality of the software
1014039Sstacze01@arm.com * licensed hereunder.  You may use the software subject to the license
1114039Sstacze01@arm.com * terms below provided that you ensure that this notice is replicated
1214039Sstacze01@arm.com * unmodified and in its entirety in all distributions of the software,
1314039Sstacze01@arm.com * modified or unmodified, in source code or in binary form.
1414039Sstacze01@arm.com *
1514039Sstacze01@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
1614039Sstacze01@arm.com * All rights reserved.
1714039Sstacze01@arm.com *
1814039Sstacze01@arm.com * Redistribution and use in source and binary forms, with or without
1914039Sstacze01@arm.com * modification, are permitted provided that the following conditions are
2014039Sstacze01@arm.com * met: redistributions of source code must retain the above copyright
2114039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer;
2214039Sstacze01@arm.com * redistributions in binary form must reproduce the above copyright
2314039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer in the
2414039Sstacze01@arm.com * documentation and/or other materials provided with the distribution;
2514039Sstacze01@arm.com * neither the name of the copyright holders nor the names of its
2614039Sstacze01@arm.com * contributors may be used to endorse or promote products derived from
2714039Sstacze01@arm.com * this software without specific prior written permission.
2814039Sstacze01@arm.com *
2914039Sstacze01@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3014039Sstacze01@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3114039Sstacze01@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3214039Sstacze01@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3314039Sstacze01@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3414039Sstacze01@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3514039Sstacze01@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3614039Sstacze01@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3714039Sstacze01@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3814039Sstacze01@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3914039Sstacze01@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4014039Sstacze01@arm.com *
4114039Sstacze01@arm.com * Authors: Steve Reinhardt
4214039Sstacze01@arm.com */
4314039Sstacze01@arm.com
4414039Sstacze01@arm.com#include "arch/kernel_stats.hh"
4514039Sstacze01@arm.com#include "arch/stacktrace.hh"
4614039Sstacze01@arm.com#include "arch/tlb.hh"
4714039Sstacze01@arm.com#include "arch/utility.hh"
4814039Sstacze01@arm.com#include "arch/vtophys.hh"
4914039Sstacze01@arm.com#include "base/loader/symtab.hh"
5014039Sstacze01@arm.com#include "base/cp_annotate.hh"
5114039Sstacze01@arm.com#include "base/cprintf.hh"
5214039Sstacze01@arm.com#include "base/inifile.hh"
5314039Sstacze01@arm.com#include "base/misc.hh"
5414039Sstacze01@arm.com#include "base/pollevent.hh"
5514039Sstacze01@arm.com#include "base/trace.hh"
5614039Sstacze01@arm.com#include "base/types.hh"
5714039Sstacze01@arm.com#include "config/the_isa.hh"
5814039Sstacze01@arm.com#include "cpu/simple/base.hh"
5914039Sstacze01@arm.com#include "cpu/base.hh"
6014039Sstacze01@arm.com#include "cpu/checker/cpu.hh"
6114039Sstacze01@arm.com#include "cpu/checker/thread_context.hh"
6214039Sstacze01@arm.com#include "cpu/exetrace.hh"
6314039Sstacze01@arm.com#include "cpu/pred/bpred_unit.hh"
6414039Sstacze01@arm.com#include "cpu/profile.hh"
6514039Sstacze01@arm.com#include "cpu/simple_thread.hh"
6614039Sstacze01@arm.com#include "cpu/smt.hh"
6714039Sstacze01@arm.com#include "cpu/static_inst.hh"
6814039Sstacze01@arm.com#include "cpu/thread_context.hh"
6914039Sstacze01@arm.com#include "debug/Decode.hh"
7014039Sstacze01@arm.com#include "debug/Fetch.hh"
7114039Sstacze01@arm.com#include "debug/Quiesce.hh"
7214039Sstacze01@arm.com#include "mem/mem_object.hh"
7314039Sstacze01@arm.com#include "mem/packet.hh"
7414039Sstacze01@arm.com#include "mem/request.hh"
7514039Sstacze01@arm.com#include "params/BaseSimpleCPU.hh"
7614039Sstacze01@arm.com#include "sim/byteswap.hh"
7714039Sstacze01@arm.com#include "sim/debug.hh"
7814039Sstacze01@arm.com#include "sim/faults.hh"
7914039Sstacze01@arm.com#include "sim/full_system.hh"
8014039Sstacze01@arm.com#include "sim/sim_events.hh"
8114063Sadrian.herrera@arm.com#include "sim/sim_object.hh"
8214063Sadrian.herrera@arm.com#include "sim/stats.hh"
8314063Sadrian.herrera@arm.com#include "sim/system.hh"
8414063Sadrian.herrera@arm.com
8514063Sadrian.herrera@arm.comusing namespace std;
8614063Sadrian.herrera@arm.comusing namespace TheISA;
8714063Sadrian.herrera@arm.com
8814063Sadrian.herrera@arm.comBaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p)
8914063Sadrian.herrera@arm.com    : BaseCPU(p),
9014063Sadrian.herrera@arm.com      branchPred(p->branchPred),
9114063Sadrian.herrera@arm.com      traceData(NULL), thread(NULL)
9214063Sadrian.herrera@arm.com{
9314063Sadrian.herrera@arm.com    if (FullSystem)
9414063Sadrian.herrera@arm.com        thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb,
9514063Sadrian.herrera@arm.com                                  p->isa[0]);
9614063Sadrian.herrera@arm.com    else
9714064Sadrian.herrera@arm.com        thread = new SimpleThread(this, /* thread_num */ 0, p->system,
9814064Sadrian.herrera@arm.com                                  p->workload[0], p->itb, p->dtb, p->isa[0]);
9914064Sadrian.herrera@arm.com
10014064Sadrian.herrera@arm.com    thread->setStatus(ThreadContext::Halted);
10114064Sadrian.herrera@arm.com
10214063Sadrian.herrera@arm.com    tc = thread->getTC();
10314063Sadrian.herrera@arm.com
10414039Sstacze01@arm.com    if (p->checker) {
10514039Sstacze01@arm.com        BaseCPU *temp_checker = p->checker;
10614039Sstacze01@arm.com        checker = dynamic_cast<CheckerCPU *>(temp_checker);
10714039Sstacze01@arm.com        checker->setSystem(p->system);
10814039Sstacze01@arm.com        // Manipulate thread context
10914039Sstacze01@arm.com        ThreadContext *cpu_tc = tc;
11014039Sstacze01@arm.com        tc = new CheckerThreadContext<ThreadContext>(cpu_tc, this->checker);
11114039Sstacze01@arm.com    } else {
11214039Sstacze01@arm.com        checker = NULL;
11314039Sstacze01@arm.com    }
11414039Sstacze01@arm.com
11514039Sstacze01@arm.com    numInst = 0;
11614039Sstacze01@arm.com    startNumInst = 0;
11714039Sstacze01@arm.com    numOp = 0;
11814039Sstacze01@arm.com    startNumOp = 0;
11914039Sstacze01@arm.com    numLoad = 0;
12014039Sstacze01@arm.com    startNumLoad = 0;
12114039Sstacze01@arm.com    lastIcacheStall = 0;
12214039Sstacze01@arm.com    lastDcacheStall = 0;
12314039Sstacze01@arm.com
12414039Sstacze01@arm.com    threadContexts.push_back(tc);
12514039Sstacze01@arm.com
12614039Sstacze01@arm.com
12714039Sstacze01@arm.com    fetchOffset = 0;
12814039Sstacze01@arm.com    stayAtPC = false;
12914039Sstacze01@arm.com}
13014039Sstacze01@arm.com
13114039Sstacze01@arm.comBaseSimpleCPU::~BaseSimpleCPU()
13214039Sstacze01@arm.com{
13314039Sstacze01@arm.com}
13414039Sstacze01@arm.com
13514039Sstacze01@arm.comvoid
13614039Sstacze01@arm.comBaseSimpleCPU::deallocateContext(ThreadID thread_num)
13714039Sstacze01@arm.com{
13814039Sstacze01@arm.com    // for now, these are equivalent
13914039Sstacze01@arm.com    suspendContext(thread_num);
14014039Sstacze01@arm.com}
14114039Sstacze01@arm.com
14214039Sstacze01@arm.com
14314039Sstacze01@arm.comvoid
14414039Sstacze01@arm.comBaseSimpleCPU::haltContext(ThreadID thread_num)
14514039Sstacze01@arm.com{
14614039Sstacze01@arm.com    // for now, these are equivalent
14714039Sstacze01@arm.com    suspendContext(thread_num);
14814039Sstacze01@arm.com}
14914039Sstacze01@arm.com
15014039Sstacze01@arm.com
15114039Sstacze01@arm.comvoid
15214039Sstacze01@arm.comBaseSimpleCPU::regStats()
15314039Sstacze01@arm.com{
15414039Sstacze01@arm.com    using namespace Stats;
15514039Sstacze01@arm.com
15614039Sstacze01@arm.com    BaseCPU::regStats();
15714039Sstacze01@arm.com
15814039Sstacze01@arm.com    numInsts
15914039Sstacze01@arm.com        .name(name() + ".committedInsts")
16014039Sstacze01@arm.com        .desc("Number of instructions committed")
16114039Sstacze01@arm.com        ;
16214039Sstacze01@arm.com
16314039Sstacze01@arm.com    numOps
16414039Sstacze01@arm.com        .name(name() + ".committedOps")
16514039Sstacze01@arm.com        .desc("Number of ops (including micro ops) committed")
16614039Sstacze01@arm.com        ;
16714039Sstacze01@arm.com
16814039Sstacze01@arm.com    numIntAluAccesses
16914039Sstacze01@arm.com        .name(name() + ".num_int_alu_accesses")
17014039Sstacze01@arm.com        .desc("Number of integer alu accesses")
17114039Sstacze01@arm.com        ;
17214039Sstacze01@arm.com
17314039Sstacze01@arm.com    numFpAluAccesses
17414039Sstacze01@arm.com        .name(name() + ".num_fp_alu_accesses")
17514039Sstacze01@arm.com        .desc("Number of float alu accesses")
17614039Sstacze01@arm.com        ;
17714039Sstacze01@arm.com
17814039Sstacze01@arm.com    numCallsReturns
17914039Sstacze01@arm.com        .name(name() + ".num_func_calls")
18014039Sstacze01@arm.com        .desc("number of times a function call or return occured")
18114039Sstacze01@arm.com        ;
18214039Sstacze01@arm.com
18314039Sstacze01@arm.com    numCondCtrlInsts
18414039Sstacze01@arm.com        .name(name() + ".num_conditional_control_insts")
18514039Sstacze01@arm.com        .desc("number of instructions that are conditional controls")
18614039Sstacze01@arm.com        ;
18714039Sstacze01@arm.com
18814039Sstacze01@arm.com    numIntInsts
18914039Sstacze01@arm.com        .name(name() + ".num_int_insts")
19014039Sstacze01@arm.com        .desc("number of integer instructions")
19114039Sstacze01@arm.com        ;
19214039Sstacze01@arm.com
19314039Sstacze01@arm.com    numFpInsts
19414039Sstacze01@arm.com        .name(name() + ".num_fp_insts")
19514039Sstacze01@arm.com        .desc("number of float instructions")
19614039Sstacze01@arm.com        ;
19714039Sstacze01@arm.com
19814039Sstacze01@arm.com    numIntRegReads
19914039Sstacze01@arm.com        .name(name() + ".num_int_register_reads")
20014039Sstacze01@arm.com        .desc("number of times the integer registers were read")
20114039Sstacze01@arm.com        ;
20214039Sstacze01@arm.com
20314039Sstacze01@arm.com    numIntRegWrites
20414039Sstacze01@arm.com        .name(name() + ".num_int_register_writes")
20514039Sstacze01@arm.com        .desc("number of times the integer registers were written")
20614039Sstacze01@arm.com        ;
20714039Sstacze01@arm.com
20814039Sstacze01@arm.com    numFpRegReads
20914039Sstacze01@arm.com        .name(name() + ".num_fp_register_reads")
21014039Sstacze01@arm.com        .desc("number of times the floating registers were read")
21114039Sstacze01@arm.com        ;
21214039Sstacze01@arm.com
21314039Sstacze01@arm.com    numFpRegWrites
21414039Sstacze01@arm.com        .name(name() + ".num_fp_register_writes")
21514039Sstacze01@arm.com        .desc("number of times the floating registers were written")
21614039Sstacze01@arm.com        ;
21714039Sstacze01@arm.com
21814039Sstacze01@arm.com    numCCRegReads
21914039Sstacze01@arm.com        .name(name() + ".num_cc_register_reads")
22014039Sstacze01@arm.com        .desc("number of times the CC registers were read")
22114039Sstacze01@arm.com        .flags(nozero)
22214039Sstacze01@arm.com        ;
22314039Sstacze01@arm.com
22414039Sstacze01@arm.com    numCCRegWrites
22514039Sstacze01@arm.com        .name(name() + ".num_cc_register_writes")
22614039Sstacze01@arm.com        .desc("number of times the CC registers were written")
22714039Sstacze01@arm.com        .flags(nozero)
22814039Sstacze01@arm.com        ;
22914039Sstacze01@arm.com
23014039Sstacze01@arm.com    numMemRefs
23114039Sstacze01@arm.com        .name(name()+".num_mem_refs")
23214039Sstacze01@arm.com        .desc("number of memory refs")
23314039Sstacze01@arm.com        ;
23414039Sstacze01@arm.com
23514039Sstacze01@arm.com    numStoreInsts
23614039Sstacze01@arm.com        .name(name() + ".num_store_insts")
23714039Sstacze01@arm.com        .desc("Number of store instructions")
23814039Sstacze01@arm.com        ;
23914039Sstacze01@arm.com
24014039Sstacze01@arm.com    numLoadInsts
24114039Sstacze01@arm.com        .name(name() + ".num_load_insts")
24214039Sstacze01@arm.com        .desc("Number of load instructions")
24314039Sstacze01@arm.com        ;
24414039Sstacze01@arm.com
24514039Sstacze01@arm.com    notIdleFraction
24614039Sstacze01@arm.com        .name(name() + ".not_idle_fraction")
24714039Sstacze01@arm.com        .desc("Percentage of non-idle cycles")
24814039Sstacze01@arm.com        ;
24914039Sstacze01@arm.com
25014039Sstacze01@arm.com    idleFraction
25114039Sstacze01@arm.com        .name(name() + ".idle_fraction")
25214039Sstacze01@arm.com        .desc("Percentage of idle cycles")
25314039Sstacze01@arm.com        ;
25414039Sstacze01@arm.com
25514039Sstacze01@arm.com    numBusyCycles
25614039Sstacze01@arm.com        .name(name() + ".num_busy_cycles")
25714039Sstacze01@arm.com        .desc("Number of busy cycles")
25814039Sstacze01@arm.com        ;
25914039Sstacze01@arm.com
26014039Sstacze01@arm.com    numIdleCycles
26114039Sstacze01@arm.com        .name(name()+".num_idle_cycles")
26214039Sstacze01@arm.com        .desc("Number of idle cycles")
26314039Sstacze01@arm.com        ;
26414039Sstacze01@arm.com
26514039Sstacze01@arm.com    icacheStallCycles
26614039Sstacze01@arm.com        .name(name() + ".icache_stall_cycles")
26714039Sstacze01@arm.com        .desc("ICache total stall cycles")
26814039Sstacze01@arm.com        .prereq(icacheStallCycles)
26914039Sstacze01@arm.com        ;
27014039Sstacze01@arm.com
27114039Sstacze01@arm.com    dcacheStallCycles
27214039Sstacze01@arm.com        .name(name() + ".dcache_stall_cycles")
27314039Sstacze01@arm.com        .desc("DCache total stall cycles")
27414039Sstacze01@arm.com        .prereq(dcacheStallCycles)
27514039Sstacze01@arm.com        ;
27614039Sstacze01@arm.com
27714039Sstacze01@arm.com    icacheRetryCycles
27814039Sstacze01@arm.com        .name(name() + ".icache_retry_cycles")
27914039Sstacze01@arm.com        .desc("ICache total retry cycles")
28014039Sstacze01@arm.com        .prereq(icacheRetryCycles)
28114039Sstacze01@arm.com        ;
28214039Sstacze01@arm.com
28314039Sstacze01@arm.com    dcacheRetryCycles
28414039Sstacze01@arm.com        .name(name() + ".dcache_retry_cycles")
28514039Sstacze01@arm.com        .desc("DCache total retry cycles")
28614039Sstacze01@arm.com        .prereq(dcacheRetryCycles)
28714039Sstacze01@arm.com        ;
28814039Sstacze01@arm.com
28914039Sstacze01@arm.com    idleFraction = constant(1.0) - notIdleFraction;
29014039Sstacze01@arm.com    numIdleCycles = idleFraction * numCycles;
29114039Sstacze01@arm.com    numBusyCycles = (notIdleFraction)*numCycles;
29214039Sstacze01@arm.com
29314039Sstacze01@arm.com    numBranches
29414039Sstacze01@arm.com        .name(name() + ".Branches")
29514039Sstacze01@arm.com        .desc("Number of branches fetched")
29614039Sstacze01@arm.com        .prereq(numBranches);
29714039Sstacze01@arm.com
29814039Sstacze01@arm.com    numPredictedBranches
29914039Sstacze01@arm.com        .name(name() + ".predictedBranches")
30014039Sstacze01@arm.com        .desc("Number of branches predicted as taken")
30114039Sstacze01@arm.com        .prereq(numPredictedBranches);
30214039Sstacze01@arm.com
30314039Sstacze01@arm.com    numBranchMispred
30414039Sstacze01@arm.com        .name(name() + ".BranchMispred")
30514039Sstacze01@arm.com        .desc("Number of branch mispredictions")
30614039Sstacze01@arm.com        .prereq(numBranchMispred);
30714039Sstacze01@arm.com}
30814039Sstacze01@arm.com
30914039Sstacze01@arm.comvoid
31014039Sstacze01@arm.comBaseSimpleCPU::resetStats()
31114039Sstacze01@arm.com{
31214039Sstacze01@arm.com//    startNumInst = numInst;
31314039Sstacze01@arm.com     notIdleFraction = (_status != Idle);
31414039Sstacze01@arm.com}
31514039Sstacze01@arm.com
31614039Sstacze01@arm.comvoid
31714039Sstacze01@arm.comBaseSimpleCPU::serializeThread(ostream &os, ThreadID tid)
31814039Sstacze01@arm.com{
31914039Sstacze01@arm.com    assert(_status == Idle || _status == Running);
32014039Sstacze01@arm.com    assert(tid == 0);
32114039Sstacze01@arm.com
32214039Sstacze01@arm.com    thread->serialize(os);
32314039Sstacze01@arm.com}
32414039Sstacze01@arm.com
32514039Sstacze01@arm.comvoid
32614039Sstacze01@arm.comBaseSimpleCPU::unserializeThread(Checkpoint *cp, const string &section,
32714039Sstacze01@arm.com                                 ThreadID tid)
32814039Sstacze01@arm.com{
32914039Sstacze01@arm.com    if (tid != 0)
33014039Sstacze01@arm.com        fatal("Trying to load more than one thread into a SimpleCPU\n");
33114039Sstacze01@arm.com    thread->unserialize(cp, section);
33214039Sstacze01@arm.com}
33314039Sstacze01@arm.com
33414039Sstacze01@arm.comvoid
33514039Sstacze01@arm.comchange_thread_state(ThreadID tid, int activate, int priority)
33614039Sstacze01@arm.com{
33714039Sstacze01@arm.com}
33814039Sstacze01@arm.com
33914039Sstacze01@arm.comAddr
34014039Sstacze01@arm.comBaseSimpleCPU::dbg_vtophys(Addr addr)
34114039Sstacze01@arm.com{
34214039Sstacze01@arm.com    return vtophys(tc, addr);
34314039Sstacze01@arm.com}
34414039Sstacze01@arm.com
34514039Sstacze01@arm.comvoid
34614039Sstacze01@arm.comBaseSimpleCPU::wakeup()
34714039Sstacze01@arm.com{
34814039Sstacze01@arm.com    if (thread->status() != ThreadContext::Suspended)
34914039Sstacze01@arm.com        return;
35014039Sstacze01@arm.com
35114039Sstacze01@arm.com    DPRINTF(Quiesce,"Suspended Processor awoke\n");
35214039Sstacze01@arm.com    thread->activate();
35314039Sstacze01@arm.com}
35414039Sstacze01@arm.com
35514039Sstacze01@arm.comvoid
35614039Sstacze01@arm.comBaseSimpleCPU::checkForInterrupts()
35714039Sstacze01@arm.com{
35814039Sstacze01@arm.com    if (checkInterrupts(tc)) {
35914039Sstacze01@arm.com        Fault interrupt = interrupts->getInterrupt(tc);
36014039Sstacze01@arm.com
36114039Sstacze01@arm.com        if (interrupt != NoFault) {
36214039Sstacze01@arm.com            fetchOffset = 0;
36314039Sstacze01@arm.com            interrupts->updateIntrInfo(tc);
36414039Sstacze01@arm.com            interrupt->invoke(tc);
36514039Sstacze01@arm.com            thread->decoder.reset();
36614039Sstacze01@arm.com        }
36714039Sstacze01@arm.com    }
36814039Sstacze01@arm.com}
36914039Sstacze01@arm.com
37014039Sstacze01@arm.com
37114039Sstacze01@arm.comvoid
37214039Sstacze01@arm.comBaseSimpleCPU::setupFetchRequest(Request *req)
37314039Sstacze01@arm.com{
37414039Sstacze01@arm.com    Addr instAddr = thread->instAddr();
37514039Sstacze01@arm.com
37614039Sstacze01@arm.com    // set up memory request for instruction fetch
37714039Sstacze01@arm.com    DPRINTF(Fetch, "Fetch: PC:%08p\n", instAddr);
37814039Sstacze01@arm.com
37914039Sstacze01@arm.com    Addr fetchPC = (instAddr & PCMask) + fetchOffset;
38014039Sstacze01@arm.com    req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH, instMasterId(),
38114039Sstacze01@arm.com            instAddr);
38214039Sstacze01@arm.com}
38314039Sstacze01@arm.com
38414039Sstacze01@arm.com
38514039Sstacze01@arm.comvoid
38614039Sstacze01@arm.comBaseSimpleCPU::preExecute()
38714039Sstacze01@arm.com{
38814039Sstacze01@arm.com    // maintain $r0 semantics
38914039Sstacze01@arm.com    thread->setIntReg(ZeroReg, 0);
39014039Sstacze01@arm.com#if THE_ISA == ALPHA_ISA
39114039Sstacze01@arm.com    thread->setFloatReg(ZeroReg, 0.0);
39214039Sstacze01@arm.com#endif // ALPHA_ISA
39314039Sstacze01@arm.com
39414039Sstacze01@arm.com    // check for instruction-count-based events
39514039Sstacze01@arm.com    comInstEventQueue[0]->serviceEvents(numInst);
39614039Sstacze01@arm.com    system->instEventQueue.serviceEvents(system->totalNumInsts);
39714039Sstacze01@arm.com
39814039Sstacze01@arm.com    // decode the instruction
39914039Sstacze01@arm.com    inst = gtoh(inst);
40014039Sstacze01@arm.com
40114039Sstacze01@arm.com    TheISA::PCState pcState = thread->pcState();
40214039Sstacze01@arm.com
40314039Sstacze01@arm.com    if (isRomMicroPC(pcState.microPC())) {
40414039Sstacze01@arm.com        stayAtPC = false;
40514039Sstacze01@arm.com        curStaticInst = microcodeRom.fetchMicroop(pcState.microPC(),
40614039Sstacze01@arm.com                                                  curMacroStaticInst);
40714039Sstacze01@arm.com    } else if (!curMacroStaticInst) {
40814039Sstacze01@arm.com        //We're not in the middle of a macro instruction
40914039Sstacze01@arm.com        StaticInstPtr instPtr = NULL;
41014039Sstacze01@arm.com
41114039Sstacze01@arm.com        TheISA::Decoder *decoder = &(thread->decoder);
41214039Sstacze01@arm.com
41314039Sstacze01@arm.com        //Predecode, ie bundle up an ExtMachInst
41414039Sstacze01@arm.com        //If more fetch data is needed, pass it in.
41514039Sstacze01@arm.com        Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset;
41614039Sstacze01@arm.com        //if(decoder->needMoreBytes())
41714039Sstacze01@arm.com            decoder->moreBytes(pcState, fetchPC, inst);
41814039Sstacze01@arm.com        //else
41914039Sstacze01@arm.com        //    decoder->process();
42014039Sstacze01@arm.com
42114039Sstacze01@arm.com        //Decode an instruction if one is ready. Otherwise, we'll have to
42214039Sstacze01@arm.com        //fetch beyond the MachInst at the current pc.
42314039Sstacze01@arm.com        instPtr = decoder->decode(pcState);
42414039Sstacze01@arm.com        if (instPtr) {
42514039Sstacze01@arm.com            stayAtPC = false;
42614039Sstacze01@arm.com            thread->pcState(pcState);
42714039Sstacze01@arm.com        } else {
42814039Sstacze01@arm.com            stayAtPC = true;
42914039Sstacze01@arm.com            fetchOffset += sizeof(MachInst);
43014039Sstacze01@arm.com        }
43114039Sstacze01@arm.com
43214039Sstacze01@arm.com        //If we decoded an instruction and it's microcoded, start pulling
43314039Sstacze01@arm.com        //out micro ops
43414039Sstacze01@arm.com        if (instPtr && instPtr->isMacroop()) {
43514039Sstacze01@arm.com            curMacroStaticInst = instPtr;
43614039Sstacze01@arm.com            curStaticInst = curMacroStaticInst->fetchMicroop(pcState.microPC());
43714039Sstacze01@arm.com        } else {
43814039Sstacze01@arm.com            curStaticInst = instPtr;
43914039Sstacze01@arm.com        }
44014039Sstacze01@arm.com    } else {
44114039Sstacze01@arm.com        //Read the next micro op from the macro op
44214039Sstacze01@arm.com        curStaticInst = curMacroStaticInst->fetchMicroop(pcState.microPC());
44314039Sstacze01@arm.com    }
44414039Sstacze01@arm.com
44514039Sstacze01@arm.com    //If we decoded an instruction this "tick", record information about it.
44614039Sstacze01@arm.com    if (curStaticInst) {
44714039Sstacze01@arm.com#if TRACING_ON
44814039Sstacze01@arm.com        traceData = tracer->getInstRecord(curTick(), tc,
44914039Sstacze01@arm.com                curStaticInst, thread->pcState(), curMacroStaticInst);
45014039Sstacze01@arm.com
45114039Sstacze01@arm.com        DPRINTF(Decode,"Decode: Decoded %s instruction: %#x\n",
45214039Sstacze01@arm.com                curStaticInst->getName(), curStaticInst->machInst);
45314039Sstacze01@arm.com#endif // TRACING_ON
45414039Sstacze01@arm.com    }
45514039Sstacze01@arm.com
45614039Sstacze01@arm.com    if (branchPred && curStaticInst && curStaticInst->isControl()) {
45714039Sstacze01@arm.com        // Use a fake sequence number since we only have one
45814039Sstacze01@arm.com        // instruction in flight at the same time.
45914039Sstacze01@arm.com        const InstSeqNum cur_sn(0);
46014039Sstacze01@arm.com        const ThreadID tid(0);
46114039Sstacze01@arm.com        pred_pc = thread->pcState();
46214039Sstacze01@arm.com        const bool predict_taken(
46314039Sstacze01@arm.com            branchPred->predict(curStaticInst, cur_sn, pred_pc, tid));
46414039Sstacze01@arm.com
46514039Sstacze01@arm.com        if (predict_taken)
46614039Sstacze01@arm.com            ++numPredictedBranches;
46714039Sstacze01@arm.com    }
46814039Sstacze01@arm.com}
46914039Sstacze01@arm.com
47014039Sstacze01@arm.comvoid
47114039Sstacze01@arm.comBaseSimpleCPU::postExecute()
47214039Sstacze01@arm.com{
47314039Sstacze01@arm.com    assert(curStaticInst);
47414039Sstacze01@arm.com
47514039Sstacze01@arm.com    TheISA::PCState pc = tc->pcState();
47614039Sstacze01@arm.com    Addr instAddr = pc.instAddr();
47714039Sstacze01@arm.com    if (FullSystem && thread->profile) {
47814039Sstacze01@arm.com        bool usermode = TheISA::inUserMode(tc);
47914039Sstacze01@arm.com        thread->profilePC = usermode ? 1 : instAddr;
48014039Sstacze01@arm.com        ProfileNode *node = thread->profile->consume(tc, curStaticInst);
48114039Sstacze01@arm.com        if (node)
48214039Sstacze01@arm.com            thread->profileNode = node;
48314039Sstacze01@arm.com    }
48414039Sstacze01@arm.com
48514039Sstacze01@arm.com    if (curStaticInst->isMemRef()) {
48614039Sstacze01@arm.com        numMemRefs++;
48714039Sstacze01@arm.com    }
48814039Sstacze01@arm.com
48914039Sstacze01@arm.com    if (curStaticInst->isLoad()) {
49014039Sstacze01@arm.com        ++numLoad;
49114039Sstacze01@arm.com        comLoadEventQueue[0]->serviceEvents(numLoad);
49214039Sstacze01@arm.com    }
49314039Sstacze01@arm.com
49414039Sstacze01@arm.com    if (CPA::available()) {
49514039Sstacze01@arm.com        CPA::cpa()->swAutoBegin(tc, pc.nextInstAddr());
49614039Sstacze01@arm.com    }
49714039Sstacze01@arm.com
49814039Sstacze01@arm.com    if (curStaticInst->isControl()) {
49914039Sstacze01@arm.com        ++numBranches;
50014039Sstacze01@arm.com    }
50114039Sstacze01@arm.com
50214039Sstacze01@arm.com    /* Power model statistics */
50314039Sstacze01@arm.com    //integer alu accesses
50414039Sstacze01@arm.com    if (curStaticInst->isInteger()){
50514039Sstacze01@arm.com        numIntAluAccesses++;
50614039Sstacze01@arm.com        numIntInsts++;
50714039Sstacze01@arm.com    }
50814039Sstacze01@arm.com
50914039Sstacze01@arm.com    //float alu accesses
51014039Sstacze01@arm.com    if (curStaticInst->isFloating()){
51114039Sstacze01@arm.com        numFpAluAccesses++;
51214039Sstacze01@arm.com        numFpInsts++;
51314039Sstacze01@arm.com    }
51414039Sstacze01@arm.com
51514039Sstacze01@arm.com    //number of function calls/returns to get window accesses
51614039Sstacze01@arm.com    if (curStaticInst->isCall() || curStaticInst->isReturn()){
51714039Sstacze01@arm.com        numCallsReturns++;
51814039Sstacze01@arm.com    }
51914039Sstacze01@arm.com
52014039Sstacze01@arm.com    //the number of branch predictions that will be made
52114039Sstacze01@arm.com    if (curStaticInst->isCondCtrl()){
52214039Sstacze01@arm.com        numCondCtrlInsts++;
52314039Sstacze01@arm.com    }
52414039Sstacze01@arm.com
52514039Sstacze01@arm.com    //result bus acceses
52614039Sstacze01@arm.com    if (curStaticInst->isLoad()){
52714039Sstacze01@arm.com        numLoadInsts++;
52814039Sstacze01@arm.com    }
52914039Sstacze01@arm.com
53014039Sstacze01@arm.com    if (curStaticInst->isStore()){
53114039Sstacze01@arm.com        numStoreInsts++;
53214039Sstacze01@arm.com    }
53314039Sstacze01@arm.com    /* End power model statistics */
53414039Sstacze01@arm.com
53514101Sgiacomo.travaglini@arm.com    if (FullSystem)
53614101Sgiacomo.travaglini@arm.com        traceFunctions(instAddr);
53714101Sgiacomo.travaglini@arm.com
53814039Sstacze01@arm.com    if (traceData) {
53914039Sstacze01@arm.com        traceData->dump();
54014039Sstacze01@arm.com        delete traceData;
54114039Sstacze01@arm.com        traceData = NULL;
54214039Sstacze01@arm.com    }
54314039Sstacze01@arm.com}
54414039Sstacze01@arm.com
54514039Sstacze01@arm.comvoid
54614039Sstacze01@arm.comBaseSimpleCPU::advancePC(Fault fault)
54714039Sstacze01@arm.com{
54814039Sstacze01@arm.com    const bool branching(thread->pcState().branching());
54914039Sstacze01@arm.com
55014039Sstacze01@arm.com    //Since we're moving to a new pc, zero out the offset
55114039Sstacze01@arm.com    fetchOffset = 0;
55214039Sstacze01@arm.com    if (fault != NoFault) {
55314039Sstacze01@arm.com        curMacroStaticInst = StaticInst::nullStaticInstPtr;
55414039Sstacze01@arm.com        fault->invoke(tc, curStaticInst);
55514039Sstacze01@arm.com        thread->decoder.reset();
55614039Sstacze01@arm.com    } else {
55714039Sstacze01@arm.com        if (curStaticInst) {
55814039Sstacze01@arm.com            if (curStaticInst->isLastMicroop())
55914039Sstacze01@arm.com                curMacroStaticInst = StaticInst::nullStaticInstPtr;
56014039Sstacze01@arm.com            TheISA::PCState pcState = thread->pcState();
56114101Sgiacomo.travaglini@arm.com            TheISA::advancePC(pcState, curStaticInst);
56214101Sgiacomo.travaglini@arm.com            thread->pcState(pcState);
56314039Sstacze01@arm.com        }
56414039Sstacze01@arm.com    }
56514039Sstacze01@arm.com
56614039Sstacze01@arm.com    if (branchPred && curStaticInst && curStaticInst->isControl()) {
56714039Sstacze01@arm.com        // Use a fake sequence number since we only have one
56814039Sstacze01@arm.com        // instruction in flight at the same time.
56914039Sstacze01@arm.com        const InstSeqNum cur_sn(0);
57014039Sstacze01@arm.com        const ThreadID tid(0);
57114039Sstacze01@arm.com
57214039Sstacze01@arm.com        if (pred_pc == thread->pcState()) {
57314039Sstacze01@arm.com            // Correctly predicted branch
57414039Sstacze01@arm.com            branchPred->update(cur_sn, tid);
57514039Sstacze01@arm.com        } else {
57614039Sstacze01@arm.com            // Mis-predicted branch
57714039Sstacze01@arm.com            branchPred->squash(cur_sn, pcState(),
57814039Sstacze01@arm.com                               branching, tid);
57914039Sstacze01@arm.com            ++numBranchMispred;
58014039Sstacze01@arm.com        }
58114039Sstacze01@arm.com    }
58214039Sstacze01@arm.com}
58314039Sstacze01@arm.com
58414039Sstacze01@arm.comvoid
58514039Sstacze01@arm.comBaseSimpleCPU::startup()
58614039Sstacze01@arm.com{
58714039Sstacze01@arm.com    BaseCPU::startup();
58814039Sstacze01@arm.com    thread->startup();
58914039Sstacze01@arm.com}
59014039Sstacze01@arm.com