cpu.cc revision 11793
112854Sgabeblack@google.com/*
212854Sgabeblack@google.com * Copyright (c) 2011-2012, 2014 ARM Limited
312854Sgabeblack@google.com * Copyright (c) 2013 Advanced Micro Devices, Inc.
412854Sgabeblack@google.com * All rights reserved
512854Sgabeblack@google.com *
612854Sgabeblack@google.com * The license below extends only to copyright in the software and shall
712854Sgabeblack@google.com * not be construed as granting a license to any other intellectual
812854Sgabeblack@google.com * property including but not limited to intellectual property relating
912854Sgabeblack@google.com * to a hardware implementation of the functionality of the software
1012854Sgabeblack@google.com * licensed hereunder.  You may use the software subject to the license
1112854Sgabeblack@google.com * terms below provided that you ensure that this notice is replicated
1212854Sgabeblack@google.com * unmodified and in its entirety in all distributions of the software,
1312854Sgabeblack@google.com * modified or unmodified, in source code or in binary form.
1412854Sgabeblack@google.com *
1512854Sgabeblack@google.com * Copyright (c) 2004-2006 The Regents of The University of Michigan
1612854Sgabeblack@google.com * Copyright (c) 2011 Regents of the University of California
1712854Sgabeblack@google.com * All rights reserved.
1812854Sgabeblack@google.com *
1912854Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
2012854Sgabeblack@google.com * modification, are permitted provided that the following conditions are
2112854Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
2212854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
2312854Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
2412854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
2512854Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
2612854Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
2712854Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
2812854Sgabeblack@google.com * this software without specific prior written permission.
2912854Sgabeblack@google.com *
3012854Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3112854Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3212854Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3312854Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3412854Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3512854Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3612854Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3712854Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3812854Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3912854Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4012854Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4112854Sgabeblack@google.com *
4212854Sgabeblack@google.com * Authors: Kevin Lim
4312854Sgabeblack@google.com *          Korey Sewell
4412854Sgabeblack@google.com *          Rick Strong
4512854Sgabeblack@google.com */
4612854Sgabeblack@google.com
4712854Sgabeblack@google.com#include "cpu/o3/cpu.hh"
4812854Sgabeblack@google.com
4912854Sgabeblack@google.com#include "arch/kernel_stats.hh"
5012854Sgabeblack@google.com#include "config/the_isa.hh"
5112854Sgabeblack@google.com#include "cpu/activity.hh"
5212854Sgabeblack@google.com#include "cpu/checker/cpu.hh"
5312854Sgabeblack@google.com#include "cpu/checker/thread_context.hh"
5412854Sgabeblack@google.com#include "cpu/o3/isa_specific.hh"
5512854Sgabeblack@google.com#include "cpu/o3/thread_context.hh"
5612854Sgabeblack@google.com#include "cpu/quiesce_event.hh"
5712854Sgabeblack@google.com#include "cpu/simple_thread.hh"
5812854Sgabeblack@google.com#include "cpu/thread_context.hh"
5912854Sgabeblack@google.com#include "debug/Activity.hh"
6012854Sgabeblack@google.com#include "debug/Drain.hh"
6112854Sgabeblack@google.com#include "debug/O3CPU.hh"
6212854Sgabeblack@google.com#include "debug/Quiesce.hh"
6312854Sgabeblack@google.com#include "enums/MemoryMode.hh"
6412854Sgabeblack@google.com#include "sim/core.hh"
6512854Sgabeblack@google.com#include "sim/full_system.hh"
6612854Sgabeblack@google.com#include "sim/process.hh"
6712854Sgabeblack@google.com#include "sim/stat_control.hh"
6812854Sgabeblack@google.com#include "sim/system.hh"
6912854Sgabeblack@google.com
7012854Sgabeblack@google.com#if THE_ISA == ALPHA_ISA
7112854Sgabeblack@google.com#include "arch/alpha/osfpal.hh"
7212854Sgabeblack@google.com#include "debug/Activity.hh"
7312854Sgabeblack@google.com
7412854Sgabeblack@google.com#endif
7512854Sgabeblack@google.com
7612854Sgabeblack@google.comstruct BaseCPUParams;
7712854Sgabeblack@google.com
7812854Sgabeblack@google.comusing namespace TheISA;
7912854Sgabeblack@google.comusing namespace std;
8012854Sgabeblack@google.com
8112854Sgabeblack@google.comBaseO3CPU::BaseO3CPU(BaseCPUParams *params)
8212854Sgabeblack@google.com    : BaseCPU(params)
8312854Sgabeblack@google.com{
8412854Sgabeblack@google.com}
8512854Sgabeblack@google.com
8612854Sgabeblack@google.comvoid
8712854Sgabeblack@google.comBaseO3CPU::regStats()
8812854Sgabeblack@google.com{
8912854Sgabeblack@google.com    BaseCPU::regStats();
9012854Sgabeblack@google.com}
9112854Sgabeblack@google.com
9212854Sgabeblack@google.comtemplate<class Impl>
9312854Sgabeblack@google.combool
9412854Sgabeblack@google.comFullO3CPU<Impl>::IcachePort::recvTimingResp(PacketPtr pkt)
9512854Sgabeblack@google.com{
9612854Sgabeblack@google.com    DPRINTF(O3CPU, "Fetch unit received timing\n");
9712854Sgabeblack@google.com    // We shouldn't ever get a cacheable block in Modified state
9812854Sgabeblack@google.com    assert(pkt->req->isUncacheable() ||
9912854Sgabeblack@google.com           !(pkt->cacheResponding() && !pkt->hasSharers()));
10012854Sgabeblack@google.com    fetch->processCacheCompletion(pkt);
10112854Sgabeblack@google.com
10212854Sgabeblack@google.com    return true;
10312854Sgabeblack@google.com}
10412854Sgabeblack@google.com
10512854Sgabeblack@google.comtemplate<class Impl>
10612854Sgabeblack@google.comvoid
10712854Sgabeblack@google.comFullO3CPU<Impl>::IcachePort::recvReqRetry()
10812854Sgabeblack@google.com{
10912854Sgabeblack@google.com    fetch->recvReqRetry();
11012854Sgabeblack@google.com}
11112854Sgabeblack@google.com
11212854Sgabeblack@google.comtemplate <class Impl>
11312854Sgabeblack@google.combool
11412854Sgabeblack@google.comFullO3CPU<Impl>::DcachePort::recvTimingResp(PacketPtr pkt)
11512854Sgabeblack@google.com{
11612854Sgabeblack@google.com    return lsq->recvTimingResp(pkt);
11712854Sgabeblack@google.com}
11812854Sgabeblack@google.com
11912854Sgabeblack@google.comtemplate <class Impl>
12012854Sgabeblack@google.comvoid
12112854Sgabeblack@google.comFullO3CPU<Impl>::DcachePort::recvTimingSnoopReq(PacketPtr pkt)
12212854Sgabeblack@google.com{
12312854Sgabeblack@google.com    for (ThreadID tid = 0; tid < cpu->numThreads; tid++) {
12412854Sgabeblack@google.com        if (cpu->getCpuAddrMonitor(tid)->doMonitor(pkt)) {
12512854Sgabeblack@google.com            cpu->wakeup(tid);
12612854Sgabeblack@google.com        }
12712854Sgabeblack@google.com    }
12812854Sgabeblack@google.com    lsq->recvTimingSnoopReq(pkt);
12912854Sgabeblack@google.com}
13012854Sgabeblack@google.com
13112854Sgabeblack@google.comtemplate <class Impl>
13212854Sgabeblack@google.comvoid
13312854Sgabeblack@google.comFullO3CPU<Impl>::DcachePort::recvReqRetry()
13412854Sgabeblack@google.com{
13512854Sgabeblack@google.com    lsq->recvReqRetry();
13612854Sgabeblack@google.com}
13712854Sgabeblack@google.com
13812854Sgabeblack@google.comtemplate <class Impl>
13912854Sgabeblack@google.comFullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
14012854Sgabeblack@google.com    : Event(CPU_Tick_Pri), cpu(c)
14112854Sgabeblack@google.com{
14212854Sgabeblack@google.com}
14312854Sgabeblack@google.com
14412854Sgabeblack@google.comtemplate <class Impl>
14512854Sgabeblack@google.comvoid
14612854Sgabeblack@google.comFullO3CPU<Impl>::TickEvent::process()
14712854Sgabeblack@google.com{
14812854Sgabeblack@google.com    cpu->tick();
14912854Sgabeblack@google.com}
15012854Sgabeblack@google.com
15112854Sgabeblack@google.comtemplate <class Impl>
15212854Sgabeblack@google.comconst char *
15312854Sgabeblack@google.comFullO3CPU<Impl>::TickEvent::description() const
15412854Sgabeblack@google.com{
15512854Sgabeblack@google.com    return "FullO3CPU tick";
15612854Sgabeblack@google.com}
15712854Sgabeblack@google.com
15812854Sgabeblack@google.comtemplate <class Impl>
15912854Sgabeblack@google.comFullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
16012854Sgabeblack@google.com    : BaseO3CPU(params),
16112854Sgabeblack@google.com      itb(params->itb),
16212854Sgabeblack@google.com      dtb(params->dtb),
16312854Sgabeblack@google.com      tickEvent(this),
16412854Sgabeblack@google.com#ifndef NDEBUG
16512854Sgabeblack@google.com      instcount(0),
16612854Sgabeblack@google.com#endif
16712854Sgabeblack@google.com      removeInstsThisCycle(false),
16812854Sgabeblack@google.com      fetch(this, params),
16912854Sgabeblack@google.com      decode(this, params),
17012854Sgabeblack@google.com      rename(this, params),
17112854Sgabeblack@google.com      iew(this, params),
17212854Sgabeblack@google.com      commit(this, params),
17312854Sgabeblack@google.com
17412854Sgabeblack@google.com      regFile(params->numPhysIntRegs,
17512854Sgabeblack@google.com              params->numPhysFloatRegs,
17612854Sgabeblack@google.com              params->numPhysCCRegs),
17712854Sgabeblack@google.com
17812854Sgabeblack@google.com      freeList(name() + ".freelist", &regFile),
17912854Sgabeblack@google.com
18012854Sgabeblack@google.com      rob(this, params),
18112854Sgabeblack@google.com
18212854Sgabeblack@google.com      scoreboard(name() + ".scoreboard",
18312854Sgabeblack@google.com                 regFile.totalNumPhysRegs(), TheISA::NumMiscRegs,
18412854Sgabeblack@google.com                 TheISA::ZeroReg, TheISA::ZeroReg),
18512854Sgabeblack@google.com
18612854Sgabeblack@google.com      isa(numThreads, NULL),
18712854Sgabeblack@google.com
18812854Sgabeblack@google.com      icachePort(&fetch, this),
18912854Sgabeblack@google.com      dcachePort(&iew.ldstQueue, this),
19012854Sgabeblack@google.com
19112854Sgabeblack@google.com      timeBuffer(params->backComSize, params->forwardComSize),
19212854Sgabeblack@google.com      fetchQueue(params->backComSize, params->forwardComSize),
19312854Sgabeblack@google.com      decodeQueue(params->backComSize, params->forwardComSize),
19412854Sgabeblack@google.com      renameQueue(params->backComSize, params->forwardComSize),
19512854Sgabeblack@google.com      iewQueue(params->backComSize, params->forwardComSize),
19612854Sgabeblack@google.com      activityRec(name(), NumStages,
19712854Sgabeblack@google.com                  params->backComSize + params->forwardComSize,
19812854Sgabeblack@google.com                  params->activity),
19912854Sgabeblack@google.com
20012854Sgabeblack@google.com      globalSeqNum(1),
20112854Sgabeblack@google.com      system(params->system),
20212854Sgabeblack@google.com      lastRunningCycle(curCycle())
20312854Sgabeblack@google.com{
20412854Sgabeblack@google.com    if (!params->switched_out) {
20512854Sgabeblack@google.com        _status = Running;
20612854Sgabeblack@google.com    } else {
20712854Sgabeblack@google.com        _status = SwitchedOut;
20812854Sgabeblack@google.com    }
20912854Sgabeblack@google.com
21012854Sgabeblack@google.com    if (params->checker) {
21112854Sgabeblack@google.com        BaseCPU *temp_checker = params->checker;
21212854Sgabeblack@google.com        checker = dynamic_cast<Checker<Impl> *>(temp_checker);
21312854Sgabeblack@google.com        checker->setIcachePort(&icachePort);
21412854Sgabeblack@google.com        checker->setSystem(params->system);
21512854Sgabeblack@google.com    } else {
21612854Sgabeblack@google.com        checker = NULL;
21712854Sgabeblack@google.com    }
21812854Sgabeblack@google.com
21912854Sgabeblack@google.com    if (!FullSystem) {
22012854Sgabeblack@google.com        thread.resize(numThreads);
22112854Sgabeblack@google.com        tids.resize(numThreads);
22212854Sgabeblack@google.com    }
22312854Sgabeblack@google.com
22412854Sgabeblack@google.com    // The stages also need their CPU pointer setup.  However this
22512854Sgabeblack@google.com    // must be done at the upper level CPU because they have pointers
22612854Sgabeblack@google.com    // to the upper level CPU, and not this FullO3CPU.
22712854Sgabeblack@google.com
22812854Sgabeblack@google.com    // Set up Pointers to the activeThreads list for each stage
22912854Sgabeblack@google.com    fetch.setActiveThreads(&activeThreads);
23012854Sgabeblack@google.com    decode.setActiveThreads(&activeThreads);
23112854Sgabeblack@google.com    rename.setActiveThreads(&activeThreads);
23212854Sgabeblack@google.com    iew.setActiveThreads(&activeThreads);
23312854Sgabeblack@google.com    commit.setActiveThreads(&activeThreads);
23412854Sgabeblack@google.com
23512854Sgabeblack@google.com    // Give each of the stages the time buffer they will use.
23612854Sgabeblack@google.com    fetch.setTimeBuffer(&timeBuffer);
23712854Sgabeblack@google.com    decode.setTimeBuffer(&timeBuffer);
23812854Sgabeblack@google.com    rename.setTimeBuffer(&timeBuffer);
23912854Sgabeblack@google.com    iew.setTimeBuffer(&timeBuffer);
24012854Sgabeblack@google.com    commit.setTimeBuffer(&timeBuffer);
24112854Sgabeblack@google.com
24212854Sgabeblack@google.com    // Also setup each of the stages' queues.
24312854Sgabeblack@google.com    fetch.setFetchQueue(&fetchQueue);
24412854Sgabeblack@google.com    decode.setFetchQueue(&fetchQueue);
24512854Sgabeblack@google.com    commit.setFetchQueue(&fetchQueue);
24612854Sgabeblack@google.com    decode.setDecodeQueue(&decodeQueue);
24712854Sgabeblack@google.com    rename.setDecodeQueue(&decodeQueue);
24812854Sgabeblack@google.com    rename.setRenameQueue(&renameQueue);
24912854Sgabeblack@google.com    iew.setRenameQueue(&renameQueue);
25012854Sgabeblack@google.com    iew.setIEWQueue(&iewQueue);
25112854Sgabeblack@google.com    commit.setIEWQueue(&iewQueue);
25212854Sgabeblack@google.com    commit.setRenameQueue(&renameQueue);
25312854Sgabeblack@google.com
25412854Sgabeblack@google.com    commit.setIEWStage(&iew);
25512854Sgabeblack@google.com    rename.setIEWStage(&iew);
25612854Sgabeblack@google.com    rename.setCommitStage(&commit);
25712854Sgabeblack@google.com
25812854Sgabeblack@google.com    ThreadID active_threads;
25912854Sgabeblack@google.com    if (FullSystem) {
26012854Sgabeblack@google.com        active_threads = 1;
26112854Sgabeblack@google.com    } else {
26212854Sgabeblack@google.com        active_threads = params->workload.size();
26312854Sgabeblack@google.com
26412854Sgabeblack@google.com        if (active_threads > Impl::MaxThreads) {
26512854Sgabeblack@google.com            panic("Workload Size too large. Increase the 'MaxThreads' "
26612854Sgabeblack@google.com                  "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) "
26712854Sgabeblack@google.com                  "or edit your workload size.");
26812854Sgabeblack@google.com        }
26912854Sgabeblack@google.com    }
27012854Sgabeblack@google.com
27112854Sgabeblack@google.com    //Make Sure That this a Valid Architeture
27212854Sgabeblack@google.com    assert(params->numPhysIntRegs   >= numThreads * TheISA::NumIntRegs);
27312854Sgabeblack@google.com    assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
27412854Sgabeblack@google.com    assert(params->numPhysCCRegs >= numThreads * TheISA::NumCCRegs);
27512854Sgabeblack@google.com
27612854Sgabeblack@google.com    rename.setScoreboard(&scoreboard);
27712854Sgabeblack@google.com    iew.setScoreboard(&scoreboard);
27812854Sgabeblack@google.com
27912854Sgabeblack@google.com    // Setup the rename map for whichever stages need it.
28012854Sgabeblack@google.com    for (ThreadID tid = 0; tid < numThreads; tid++) {
28112854Sgabeblack@google.com        isa[tid] = params->isa[tid];
28212854Sgabeblack@google.com
28312854Sgabeblack@google.com        // Only Alpha has an FP zero register, so for other ISAs we
28412854Sgabeblack@google.com        // use an invalid FP register index to avoid special treatment
28512854Sgabeblack@google.com        // of any valid FP reg.
28612854Sgabeblack@google.com        RegIndex invalidFPReg = TheISA::NumFloatRegs + 1;
28712854Sgabeblack@google.com        RegIndex fpZeroReg =
28812854Sgabeblack@google.com            (THE_ISA == ALPHA_ISA) ? TheISA::ZeroReg : invalidFPReg;
28912854Sgabeblack@google.com
29012854Sgabeblack@google.com        commitRenameMap[tid].init(&regFile, TheISA::ZeroReg, fpZeroReg,
29112854Sgabeblack@google.com                                  &freeList);
29212854Sgabeblack@google.com
29312854Sgabeblack@google.com        renameMap[tid].init(&regFile, TheISA::ZeroReg, fpZeroReg,
29412854Sgabeblack@google.com                            &freeList);
29512854Sgabeblack@google.com    }
29612854Sgabeblack@google.com
29712854Sgabeblack@google.com    // Initialize rename map to assign physical registers to the
29812854Sgabeblack@google.com    // architectural registers for active threads only.
29912854Sgabeblack@google.com    for (ThreadID tid = 0; tid < active_threads; tid++) {
30012854Sgabeblack@google.com        for (RegIndex ridx = 0; ridx < TheISA::NumIntRegs; ++ridx) {
30112854Sgabeblack@google.com            // Note that we can't use the rename() method because we don't
30212854Sgabeblack@google.com            // want special treatment for the zero register at this point
30312854Sgabeblack@google.com            PhysRegIndex phys_reg = freeList.getIntReg();
30412854Sgabeblack@google.com            renameMap[tid].setIntEntry(ridx, phys_reg);
30512854Sgabeblack@google.com            commitRenameMap[tid].setIntEntry(ridx, phys_reg);
30612854Sgabeblack@google.com        }
30712854Sgabeblack@google.com
30812854Sgabeblack@google.com        for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) {
30912854Sgabeblack@google.com            PhysRegIndex phys_reg = freeList.getFloatReg();
31012854Sgabeblack@google.com            renameMap[tid].setFloatEntry(ridx, phys_reg);
31112854Sgabeblack@google.com            commitRenameMap[tid].setFloatEntry(ridx, phys_reg);
31212854Sgabeblack@google.com        }
31312854Sgabeblack@google.com
31412854Sgabeblack@google.com        for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) {
31512854Sgabeblack@google.com            PhysRegIndex phys_reg = freeList.getCCReg();
31612854Sgabeblack@google.com            renameMap[tid].setCCEntry(ridx, phys_reg);
31712854Sgabeblack@google.com            commitRenameMap[tid].setCCEntry(ridx, phys_reg);
31812854Sgabeblack@google.com        }
31912854Sgabeblack@google.com    }
32012854Sgabeblack@google.com
32112854Sgabeblack@google.com    rename.setRenameMap(renameMap);
32212854Sgabeblack@google.com    commit.setRenameMap(commitRenameMap);
32312854Sgabeblack@google.com    rename.setFreeList(&freeList);
32412854Sgabeblack@google.com
32512854Sgabeblack@google.com    // Setup the ROB for whichever stages need it.
32612854Sgabeblack@google.com    commit.setROB(&rob);
32712854Sgabeblack@google.com
32812854Sgabeblack@google.com    lastActivatedCycle = 0;
32912854Sgabeblack@google.com#if 0
33012854Sgabeblack@google.com    // Give renameMap & rename stage access to the freeList;
33112854Sgabeblack@google.com    for (ThreadID tid = 0; tid < numThreads; tid++)
33212854Sgabeblack@google.com        globalSeqNum[tid] = 1;
33312854Sgabeblack@google.com#endif
33412854Sgabeblack@google.com
33512854Sgabeblack@google.com    DPRINTF(O3CPU, "Creating O3CPU object.\n");
33612854Sgabeblack@google.com
33712854Sgabeblack@google.com    // Setup any thread state.
33812854Sgabeblack@google.com    this->thread.resize(this->numThreads);
33912854Sgabeblack@google.com
34012854Sgabeblack@google.com    for (ThreadID tid = 0; tid < this->numThreads; ++tid) {
34112854Sgabeblack@google.com        if (FullSystem) {
34212854Sgabeblack@google.com            // SMT is not supported in FS mode yet.
34312854Sgabeblack@google.com            assert(this->numThreads == 1);
34412854Sgabeblack@google.com            this->thread[tid] = new Thread(this, 0, NULL);
34512854Sgabeblack@google.com        } else {
34612854Sgabeblack@google.com            if (tid < params->workload.size()) {
34712854Sgabeblack@google.com                DPRINTF(O3CPU, "Workload[%i] process is %#x",
34812854Sgabeblack@google.com                        tid, this->thread[tid]);
34912854Sgabeblack@google.com                this->thread[tid] = new typename FullO3CPU<Impl>::Thread(
35012854Sgabeblack@google.com                        (typename Impl::O3CPU *)(this),
35112854Sgabeblack@google.com                        tid, params->workload[tid]);
35212854Sgabeblack@google.com
35312854Sgabeblack@google.com                //usedTids[tid] = true;
35412854Sgabeblack@google.com                //threadMap[tid] = tid;
35512854Sgabeblack@google.com            } else {
35612854Sgabeblack@google.com                //Allocate Empty thread so M5 can use later
35712854Sgabeblack@google.com                //when scheduling threads to CPU
35812854Sgabeblack@google.com                Process* dummy_proc = NULL;
35912854Sgabeblack@google.com
36012854Sgabeblack@google.com                this->thread[tid] = new typename FullO3CPU<Impl>::Thread(
36112854Sgabeblack@google.com                        (typename Impl::O3CPU *)(this),
36212854Sgabeblack@google.com                        tid, dummy_proc);
36312854Sgabeblack@google.com                //usedTids[tid] = false;
36412854Sgabeblack@google.com            }
36512854Sgabeblack@google.com        }
36612854Sgabeblack@google.com
36712854Sgabeblack@google.com        ThreadContext *tc;
36812854Sgabeblack@google.com
36912854Sgabeblack@google.com        // Setup the TC that will serve as the interface to the threads/CPU.
37012854Sgabeblack@google.com        O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>;
37112854Sgabeblack@google.com
37212854Sgabeblack@google.com        tc = o3_tc;
37312854Sgabeblack@google.com
37412854Sgabeblack@google.com        // If we're using a checker, then the TC should be the
37512854Sgabeblack@google.com        // CheckerThreadContext.
37612854Sgabeblack@google.com        if (params->checker) {
37712854Sgabeblack@google.com            tc = new CheckerThreadContext<O3ThreadContext<Impl> >(
37812854Sgabeblack@google.com                o3_tc, this->checker);
37912854Sgabeblack@google.com        }
38012854Sgabeblack@google.com
38112854Sgabeblack@google.com        o3_tc->cpu = (typename Impl::O3CPU *)(this);
38212854Sgabeblack@google.com        assert(o3_tc->cpu);
38312854Sgabeblack@google.com        o3_tc->thread = this->thread[tid];
38412854Sgabeblack@google.com
38512854Sgabeblack@google.com        // Setup quiesce event.
38612854Sgabeblack@google.com        this->thread[tid]->quiesceEvent = new EndQuiesceEvent(tc);
38712854Sgabeblack@google.com
38812854Sgabeblack@google.com        // Give the thread the TC.
38912854Sgabeblack@google.com        this->thread[tid]->tc = tc;
39012854Sgabeblack@google.com
39112854Sgabeblack@google.com        // Add the TC to the CPU's list of TC's.
39212854Sgabeblack@google.com        this->threadContexts.push_back(tc);
39312854Sgabeblack@google.com    }
39412854Sgabeblack@google.com
39512854Sgabeblack@google.com    // FullO3CPU always requires an interrupt controller.
39612854Sgabeblack@google.com    if (!params->switched_out && interrupts.empty()) {
39712854Sgabeblack@google.com        fatal("FullO3CPU %s has no interrupt controller.\n"
39812854Sgabeblack@google.com              "Ensure createInterruptController() is called.\n", name());
39912854Sgabeblack@google.com    }
40012854Sgabeblack@google.com
40112854Sgabeblack@google.com    for (ThreadID tid = 0; tid < this->numThreads; tid++)
40212854Sgabeblack@google.com        this->thread[tid]->setFuncExeInst(0);
40312854Sgabeblack@google.com}
40412854Sgabeblack@google.com
40512854Sgabeblack@google.comtemplate <class Impl>
40612854Sgabeblack@google.comFullO3CPU<Impl>::~FullO3CPU()
40712854Sgabeblack@google.com{
40812854Sgabeblack@google.com}
40912854Sgabeblack@google.com
41012854Sgabeblack@google.comtemplate <class Impl>
41112854Sgabeblack@google.comvoid
41212854Sgabeblack@google.comFullO3CPU<Impl>::regProbePoints()
41312854Sgabeblack@google.com{
41412854Sgabeblack@google.com    BaseCPU::regProbePoints();
41512854Sgabeblack@google.com
41612854Sgabeblack@google.com    ppInstAccessComplete = new ProbePointArg<PacketPtr>(getProbeManager(), "InstAccessComplete");
41712854Sgabeblack@google.com    ppDataAccessComplete = new ProbePointArg<std::pair<DynInstPtr, PacketPtr> >(getProbeManager(), "DataAccessComplete");
41812854Sgabeblack@google.com
41912854Sgabeblack@google.com    fetch.regProbePoints();
42012854Sgabeblack@google.com    rename.regProbePoints();
42112854Sgabeblack@google.com    iew.regProbePoints();
42212854Sgabeblack@google.com    commit.regProbePoints();
42312854Sgabeblack@google.com}
42412854Sgabeblack@google.com
42512854Sgabeblack@google.comtemplate <class Impl>
42612854Sgabeblack@google.comvoid
42712854Sgabeblack@google.comFullO3CPU<Impl>::regStats()
42812854Sgabeblack@google.com{
42912854Sgabeblack@google.com    BaseO3CPU::regStats();
43012854Sgabeblack@google.com
43112854Sgabeblack@google.com    // Register any of the O3CPU's stats here.
43212854Sgabeblack@google.com    timesIdled
43312854Sgabeblack@google.com        .name(name() + ".timesIdled")
43412854Sgabeblack@google.com        .desc("Number of times that the entire CPU went into an idle state and"
43512854Sgabeblack@google.com              " unscheduled itself")
43612854Sgabeblack@google.com        .prereq(timesIdled);
43712854Sgabeblack@google.com
43812854Sgabeblack@google.com    idleCycles
43912854Sgabeblack@google.com        .name(name() + ".idleCycles")
44012854Sgabeblack@google.com        .desc("Total number of cycles that the CPU has spent unscheduled due "
44112854Sgabeblack@google.com              "to idling")
44212854Sgabeblack@google.com        .prereq(idleCycles);
44312854Sgabeblack@google.com
44412854Sgabeblack@google.com    quiesceCycles
44512854Sgabeblack@google.com        .name(name() + ".quiesceCycles")
44612854Sgabeblack@google.com        .desc("Total number of cycles that CPU has spent quiesced or waiting "
44712854Sgabeblack@google.com              "for an interrupt")
44812854Sgabeblack@google.com        .prereq(quiesceCycles);
44912854Sgabeblack@google.com
45012854Sgabeblack@google.com    // Number of Instructions simulated
45112854Sgabeblack@google.com    // --------------------------------
45212854Sgabeblack@google.com    // Should probably be in Base CPU but need templated
45312854Sgabeblack@google.com    // MaxThreads so put in here instead
45412854Sgabeblack@google.com    committedInsts
45512854Sgabeblack@google.com        .init(numThreads)
45612854Sgabeblack@google.com        .name(name() + ".committedInsts")
45712854Sgabeblack@google.com        .desc("Number of Instructions Simulated")
45812854Sgabeblack@google.com        .flags(Stats::total);
45912854Sgabeblack@google.com
46012854Sgabeblack@google.com    committedOps
46112854Sgabeblack@google.com        .init(numThreads)
46212854Sgabeblack@google.com        .name(name() + ".committedOps")
46312854Sgabeblack@google.com        .desc("Number of Ops (including micro ops) Simulated")
46412854Sgabeblack@google.com        .flags(Stats::total);
46512854Sgabeblack@google.com
46612854Sgabeblack@google.com    cpi
46712854Sgabeblack@google.com        .name(name() + ".cpi")
46812854Sgabeblack@google.com        .desc("CPI: Cycles Per Instruction")
46912854Sgabeblack@google.com        .precision(6);
47012854Sgabeblack@google.com    cpi = numCycles / committedInsts;
47112854Sgabeblack@google.com
47212854Sgabeblack@google.com    totalCpi
47312854Sgabeblack@google.com        .name(name() + ".cpi_total")
47412854Sgabeblack@google.com        .desc("CPI: Total CPI of All Threads")
47512854Sgabeblack@google.com        .precision(6);
47612854Sgabeblack@google.com    totalCpi = numCycles / sum(committedInsts);
47712854Sgabeblack@google.com
47812854Sgabeblack@google.com    ipc
47912854Sgabeblack@google.com        .name(name() + ".ipc")
48012854Sgabeblack@google.com        .desc("IPC: Instructions Per Cycle")
48112854Sgabeblack@google.com        .precision(6);
48212854Sgabeblack@google.com    ipc =  committedInsts / numCycles;
48312854Sgabeblack@google.com
48412854Sgabeblack@google.com    totalIpc
48512854Sgabeblack@google.com        .name(name() + ".ipc_total")
48612854Sgabeblack@google.com        .desc("IPC: Total IPC of All Threads")
48712854Sgabeblack@google.com        .precision(6);
48812854Sgabeblack@google.com    totalIpc =  sum(committedInsts) / numCycles;
48912854Sgabeblack@google.com
49012854Sgabeblack@google.com    this->fetch.regStats();
49112854Sgabeblack@google.com    this->decode.regStats();
49212854Sgabeblack@google.com    this->rename.regStats();
49312854Sgabeblack@google.com    this->iew.regStats();
49412854Sgabeblack@google.com    this->commit.regStats();
49512854Sgabeblack@google.com    this->rob.regStats();
49612854Sgabeblack@google.com
49712854Sgabeblack@google.com    intRegfileReads
49812854Sgabeblack@google.com        .name(name() + ".int_regfile_reads")
49912854Sgabeblack@google.com        .desc("number of integer regfile reads")
50012854Sgabeblack@google.com        .prereq(intRegfileReads);
50112854Sgabeblack@google.com
50212854Sgabeblack@google.com    intRegfileWrites
50312854Sgabeblack@google.com        .name(name() + ".int_regfile_writes")
50412854Sgabeblack@google.com        .desc("number of integer regfile writes")
50512854Sgabeblack@google.com        .prereq(intRegfileWrites);
50612854Sgabeblack@google.com
50712854Sgabeblack@google.com    fpRegfileReads
50812854Sgabeblack@google.com        .name(name() + ".fp_regfile_reads")
50912854Sgabeblack@google.com        .desc("number of floating regfile reads")
51012854Sgabeblack@google.com        .prereq(fpRegfileReads);
51112854Sgabeblack@google.com
51212854Sgabeblack@google.com    fpRegfileWrites
51312854Sgabeblack@google.com        .name(name() + ".fp_regfile_writes")
51412854Sgabeblack@google.com        .desc("number of floating regfile writes")
51512854Sgabeblack@google.com        .prereq(fpRegfileWrites);
51612854Sgabeblack@google.com
51712854Sgabeblack@google.com    ccRegfileReads
51812854Sgabeblack@google.com        .name(name() + ".cc_regfile_reads")
51912854Sgabeblack@google.com        .desc("number of cc regfile reads")
52012854Sgabeblack@google.com        .prereq(ccRegfileReads);
52112854Sgabeblack@google.com
52212854Sgabeblack@google.com    ccRegfileWrites
52312854Sgabeblack@google.com        .name(name() + ".cc_regfile_writes")
52412854Sgabeblack@google.com        .desc("number of cc regfile writes")
52512854Sgabeblack@google.com        .prereq(ccRegfileWrites);
52612854Sgabeblack@google.com
52712854Sgabeblack@google.com    miscRegfileReads
52812854Sgabeblack@google.com        .name(name() + ".misc_regfile_reads")
52912854Sgabeblack@google.com        .desc("number of misc regfile reads")
53012854Sgabeblack@google.com        .prereq(miscRegfileReads);
53112854Sgabeblack@google.com
53212854Sgabeblack@google.com    miscRegfileWrites
53312854Sgabeblack@google.com        .name(name() + ".misc_regfile_writes")
53412854Sgabeblack@google.com        .desc("number of misc regfile writes")
53512854Sgabeblack@google.com        .prereq(miscRegfileWrites);
53612854Sgabeblack@google.com}
53712854Sgabeblack@google.com
53812854Sgabeblack@google.comtemplate <class Impl>
53912854Sgabeblack@google.comvoid
54012854Sgabeblack@google.comFullO3CPU<Impl>::tick()
54112854Sgabeblack@google.com{
54212854Sgabeblack@google.com    DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
54312854Sgabeblack@google.com    assert(!switchedOut());
54412854Sgabeblack@google.com    assert(drainState() != DrainState::Drained);
54512854Sgabeblack@google.com
54612854Sgabeblack@google.com    ++numCycles;
54712854Sgabeblack@google.com    ppCycles->notify(1);
54812854Sgabeblack@google.com
54912854Sgabeblack@google.com//    activity = false;
55012854Sgabeblack@google.com
55112854Sgabeblack@google.com    //Tick each of the stages
55212854Sgabeblack@google.com    fetch.tick();
55312854Sgabeblack@google.com
55412854Sgabeblack@google.com    decode.tick();
55512854Sgabeblack@google.com
55612854Sgabeblack@google.com    rename.tick();
55712854Sgabeblack@google.com
55812854Sgabeblack@google.com    iew.tick();
55912854Sgabeblack@google.com
56012854Sgabeblack@google.com    commit.tick();
56112854Sgabeblack@google.com
56212854Sgabeblack@google.com    // Now advance the time buffers
56312854Sgabeblack@google.com    timeBuffer.advance();
56412854Sgabeblack@google.com
56512854Sgabeblack@google.com    fetchQueue.advance();
56612854Sgabeblack@google.com    decodeQueue.advance();
56712854Sgabeblack@google.com    renameQueue.advance();
56812854Sgabeblack@google.com    iewQueue.advance();
56912854Sgabeblack@google.com
57012854Sgabeblack@google.com    activityRec.advance();
57112854Sgabeblack@google.com
57212854Sgabeblack@google.com    if (removeInstsThisCycle) {
57312854Sgabeblack@google.com        cleanUpRemovedInsts();
57412854Sgabeblack@google.com    }
57512854Sgabeblack@google.com
57612854Sgabeblack@google.com    if (!tickEvent.scheduled()) {
57712854Sgabeblack@google.com        if (_status == SwitchedOut) {
57812854Sgabeblack@google.com            DPRINTF(O3CPU, "Switched out!\n");
57912854Sgabeblack@google.com            // increment stat
58012854Sgabeblack@google.com            lastRunningCycle = curCycle();
58112854Sgabeblack@google.com        } else if (!activityRec.active() || _status == Idle) {
58212854Sgabeblack@google.com            DPRINTF(O3CPU, "Idle!\n");
58312854Sgabeblack@google.com            lastRunningCycle = curCycle();
58412854Sgabeblack@google.com            timesIdled++;
58512854Sgabeblack@google.com        } else {
58612854Sgabeblack@google.com            schedule(tickEvent, clockEdge(Cycles(1)));
58712854Sgabeblack@google.com            DPRINTF(O3CPU, "Scheduling next tick!\n");
58812854Sgabeblack@google.com        }
58912854Sgabeblack@google.com    }
59012854Sgabeblack@google.com
59112854Sgabeblack@google.com    if (!FullSystem)
59212854Sgabeblack@google.com        updateThreadPriority();
59312854Sgabeblack@google.com
59412854Sgabeblack@google.com    tryDrain();
59512854Sgabeblack@google.com}
59612854Sgabeblack@google.com
59712854Sgabeblack@google.comtemplate <class Impl>
59812854Sgabeblack@google.comvoid
59912854Sgabeblack@google.comFullO3CPU<Impl>::init()
60012854Sgabeblack@google.com{
60112854Sgabeblack@google.com    BaseCPU::init();
60212854Sgabeblack@google.com
60312854Sgabeblack@google.com    for (ThreadID tid = 0; tid < numThreads; ++tid) {
60412854Sgabeblack@google.com        // Set noSquashFromTC so that the CPU doesn't squash when initially
60512854Sgabeblack@google.com        // setting up registers.
60612854Sgabeblack@google.com        thread[tid]->noSquashFromTC = true;
60712854Sgabeblack@google.com        // Initialise the ThreadContext's memory proxies
60812854Sgabeblack@google.com        thread[tid]->initMemProxies(thread[tid]->getTC());
60912854Sgabeblack@google.com    }
61012854Sgabeblack@google.com
61112854Sgabeblack@google.com    if (FullSystem && !params()->switched_out) {
61212854Sgabeblack@google.com        for (ThreadID tid = 0; tid < numThreads; tid++) {
61312854Sgabeblack@google.com            ThreadContext *src_tc = threadContexts[tid];
61412854Sgabeblack@google.com            TheISA::initCPU(src_tc, src_tc->contextId());
61512854Sgabeblack@google.com        }
61612854Sgabeblack@google.com    }
61712854Sgabeblack@google.com
61812854Sgabeblack@google.com    // Clear noSquashFromTC.
61912854Sgabeblack@google.com    for (int tid = 0; tid < numThreads; ++tid)
62012854Sgabeblack@google.com        thread[tid]->noSquashFromTC = false;
62112854Sgabeblack@google.com
62212854Sgabeblack@google.com    commit.setThreads(thread);
62312854Sgabeblack@google.com}
62412854Sgabeblack@google.com
62512854Sgabeblack@google.comtemplate <class Impl>
62612854Sgabeblack@google.comvoid
62712854Sgabeblack@google.comFullO3CPU<Impl>::startup()
62812854Sgabeblack@google.com{
62912854Sgabeblack@google.com    BaseCPU::startup();
63012854Sgabeblack@google.com    for (int tid = 0; tid < numThreads; ++tid)
63112854Sgabeblack@google.com        isa[tid]->startup(threadContexts[tid]);
63212854Sgabeblack@google.com
63312854Sgabeblack@google.com    fetch.startupStage();
63412854Sgabeblack@google.com    decode.startupStage();
63512854Sgabeblack@google.com    iew.startupStage();
63612854Sgabeblack@google.com    rename.startupStage();
63712854Sgabeblack@google.com    commit.startupStage();
63812854Sgabeblack@google.com}
63912854Sgabeblack@google.com
64012854Sgabeblack@google.comtemplate <class Impl>
64112854Sgabeblack@google.comvoid
64212854Sgabeblack@google.comFullO3CPU<Impl>::activateThread(ThreadID tid)
64312854Sgabeblack@google.com{
64412854Sgabeblack@google.com    list<ThreadID>::iterator isActive =
64512854Sgabeblack@google.com        std::find(activeThreads.begin(), activeThreads.end(), tid);
64612854Sgabeblack@google.com
64712854Sgabeblack@google.com    DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid);
64812854Sgabeblack@google.com    assert(!switchedOut());
64912854Sgabeblack@google.com
65012854Sgabeblack@google.com    if (isActive == activeThreads.end()) {
65112854Sgabeblack@google.com        DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n",
65212854Sgabeblack@google.com                tid);
65312854Sgabeblack@google.com
65412854Sgabeblack@google.com        activeThreads.push_back(tid);
65512854Sgabeblack@google.com    }
65612854Sgabeblack@google.com}
65712854Sgabeblack@google.com
65812854Sgabeblack@google.comtemplate <class Impl>
65912854Sgabeblack@google.comvoid
66012854Sgabeblack@google.comFullO3CPU<Impl>::deactivateThread(ThreadID tid)
66112854Sgabeblack@google.com{
66212854Sgabeblack@google.com    //Remove From Active List, if Active
66312854Sgabeblack@google.com    list<ThreadID>::iterator thread_it =
66412854Sgabeblack@google.com        std::find(activeThreads.begin(), activeThreads.end(), tid);
66512854Sgabeblack@google.com
66612854Sgabeblack@google.com    DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid);
66712854Sgabeblack@google.com    assert(!switchedOut());
66812854Sgabeblack@google.com
66912854Sgabeblack@google.com    if (thread_it != activeThreads.end()) {
67012854Sgabeblack@google.com        DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
67112854Sgabeblack@google.com                tid);
67212854Sgabeblack@google.com        activeThreads.erase(thread_it);
67312854Sgabeblack@google.com    }
67412854Sgabeblack@google.com
67512854Sgabeblack@google.com    fetch.deactivateThread(tid);
67612854Sgabeblack@google.com    commit.deactivateThread(tid);
67712854Sgabeblack@google.com}
67812854Sgabeblack@google.com
67912854Sgabeblack@google.comtemplate <class Impl>
68012854Sgabeblack@google.comCounter
68112854Sgabeblack@google.comFullO3CPU<Impl>::totalInsts() const
68212854Sgabeblack@google.com{
68312854Sgabeblack@google.com    Counter total(0);
68412854Sgabeblack@google.com
68512854Sgabeblack@google.com    ThreadID size = thread.size();
68612854Sgabeblack@google.com    for (ThreadID i = 0; i < size; i++)
68712854Sgabeblack@google.com        total += thread[i]->numInst;
68812854Sgabeblack@google.com
68912854Sgabeblack@google.com    return total;
69012854Sgabeblack@google.com}
69112854Sgabeblack@google.com
69212854Sgabeblack@google.comtemplate <class Impl>
69312854Sgabeblack@google.comCounter
69412854Sgabeblack@google.comFullO3CPU<Impl>::totalOps() const
69512854Sgabeblack@google.com{
69612854Sgabeblack@google.com    Counter total(0);
69712854Sgabeblack@google.com
69812854Sgabeblack@google.com    ThreadID size = thread.size();
69912854Sgabeblack@google.com    for (ThreadID i = 0; i < size; i++)
70012854Sgabeblack@google.com        total += thread[i]->numOp;
70112854Sgabeblack@google.com
70212854Sgabeblack@google.com    return total;
70312854Sgabeblack@google.com}
70412854Sgabeblack@google.com
70512854Sgabeblack@google.comtemplate <class Impl>
70612854Sgabeblack@google.comvoid
70712854Sgabeblack@google.comFullO3CPU<Impl>::activateContext(ThreadID tid)
70812854Sgabeblack@google.com{
70912854Sgabeblack@google.com    assert(!switchedOut());
71012854Sgabeblack@google.com
71112854Sgabeblack@google.com    // Needs to set each stage to running as well.
71212854Sgabeblack@google.com    activateThread(tid);
71312854Sgabeblack@google.com
71412854Sgabeblack@google.com    // We don't want to wake the CPU if it is drained. In that case,
71512854Sgabeblack@google.com    // we just want to flag the thread as active and schedule the tick
71612854Sgabeblack@google.com    // event from drainResume() instead.
71712854Sgabeblack@google.com    if (drainState() == DrainState::Drained)
71812854Sgabeblack@google.com        return;
71912854Sgabeblack@google.com
72012854Sgabeblack@google.com    // If we are time 0 or if the last activation time is in the past,
72112854Sgabeblack@google.com    // schedule the next tick and wake up the fetch unit
72212854Sgabeblack@google.com    if (lastActivatedCycle == 0 || lastActivatedCycle < curTick()) {
72312854Sgabeblack@google.com        scheduleTickEvent(Cycles(0));
72412854Sgabeblack@google.com
72512854Sgabeblack@google.com        // Be sure to signal that there's some activity so the CPU doesn't
72612854Sgabeblack@google.com        // deschedule itself.
72712854Sgabeblack@google.com        activityRec.activity();
72812854Sgabeblack@google.com        fetch.wakeFromQuiesce();
72912854Sgabeblack@google.com
73012854Sgabeblack@google.com        Cycles cycles(curCycle() - lastRunningCycle);
73112854Sgabeblack@google.com        // @todo: This is an oddity that is only here to match the stats
73212854Sgabeblack@google.com        if (cycles != 0)
73312854Sgabeblack@google.com            --cycles;
73412854Sgabeblack@google.com        quiesceCycles += cycles;
73512854Sgabeblack@google.com
73612854Sgabeblack@google.com        lastActivatedCycle = curTick();
73712854Sgabeblack@google.com
73812854Sgabeblack@google.com        _status = Running;
73912854Sgabeblack@google.com
74012854Sgabeblack@google.com        BaseCPU::activateContext(tid);
74112854Sgabeblack@google.com    }
74212854Sgabeblack@google.com}
74312854Sgabeblack@google.com
74412854Sgabeblack@google.comtemplate <class Impl>
74512854Sgabeblack@google.comvoid
74612854Sgabeblack@google.comFullO3CPU<Impl>::suspendContext(ThreadID tid)
74712854Sgabeblack@google.com{
74812854Sgabeblack@google.com    DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
74912854Sgabeblack@google.com    assert(!switchedOut());
75012854Sgabeblack@google.com
75112854Sgabeblack@google.com    deactivateThread(tid);
75212854Sgabeblack@google.com
75312854Sgabeblack@google.com    // If this was the last thread then unschedule the tick event.
75412854Sgabeblack@google.com    if (activeThreads.size() == 0) {
75512854Sgabeblack@google.com        unscheduleTickEvent();
75612854Sgabeblack@google.com        lastRunningCycle = curCycle();
75712854Sgabeblack@google.com        _status = Idle;
75812854Sgabeblack@google.com    }
75912854Sgabeblack@google.com
76012854Sgabeblack@google.com    DPRINTF(Quiesce, "Suspending Context\n");
76112854Sgabeblack@google.com
76212854Sgabeblack@google.com    BaseCPU::suspendContext(tid);
76312854Sgabeblack@google.com}
76412854Sgabeblack@google.com
76512854Sgabeblack@google.comtemplate <class Impl>
76612854Sgabeblack@google.comvoid
76712854Sgabeblack@google.comFullO3CPU<Impl>::haltContext(ThreadID tid)
76812854Sgabeblack@google.com{
76912854Sgabeblack@google.com    //For now, this is the same as deallocate
77012854Sgabeblack@google.com    DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
77112854Sgabeblack@google.com    assert(!switchedOut());
77212854Sgabeblack@google.com
77312854Sgabeblack@google.com    deactivateThread(tid);
77412854Sgabeblack@google.com    removeThread(tid);
77512854Sgabeblack@google.com}
77612854Sgabeblack@google.com
77712854Sgabeblack@google.comtemplate <class Impl>
77812854Sgabeblack@google.comvoid
77912854Sgabeblack@google.comFullO3CPU<Impl>::insertThread(ThreadID tid)
78012854Sgabeblack@google.com{
78112854Sgabeblack@google.com    DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU");
78212854Sgabeblack@google.com    // Will change now that the PC and thread state is internal to the CPU
78312854Sgabeblack@google.com    // and not in the ThreadContext.
78412854Sgabeblack@google.com    ThreadContext *src_tc;
78512854Sgabeblack@google.com    if (FullSystem)
78612854Sgabeblack@google.com        src_tc = system->threadContexts[tid];
78712854Sgabeblack@google.com    else
78812854Sgabeblack@google.com        src_tc = tcBase(tid);
78912854Sgabeblack@google.com
79012854Sgabeblack@google.com    //Bind Int Regs to Rename Map
79112854Sgabeblack@google.com    for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
79212854Sgabeblack@google.com        PhysRegIndex phys_reg = freeList.getIntReg();
79312854Sgabeblack@google.com
79412854Sgabeblack@google.com        renameMap[tid].setEntry(ireg,phys_reg);
79512854Sgabeblack@google.com        scoreboard.setReg(phys_reg);
79612854Sgabeblack@google.com    }
79712854Sgabeblack@google.com
79812854Sgabeblack@google.com    //Bind Float Regs to Rename Map
79912854Sgabeblack@google.com    int max_reg = TheISA::FP_Reg_Base + TheISA::NumFloatRegs;
80012854Sgabeblack@google.com    for (int freg = TheISA::FP_Reg_Base; freg < max_reg; freg++) {
80112854Sgabeblack@google.com        PhysRegIndex phys_reg = freeList.getFloatReg();
80212854Sgabeblack@google.com
80312854Sgabeblack@google.com        renameMap[tid].setEntry(freg,phys_reg);
80412854Sgabeblack@google.com        scoreboard.setReg(phys_reg);
80512854Sgabeblack@google.com    }
80612854Sgabeblack@google.com
80712854Sgabeblack@google.com    //Bind condition-code Regs to Rename Map
80812854Sgabeblack@google.com    max_reg = TheISA::CC_Reg_Base + TheISA::NumCCRegs;
80912854Sgabeblack@google.com    for (int creg = TheISA::CC_Reg_Base;
81012854Sgabeblack@google.com         creg < max_reg; creg++) {
81112854Sgabeblack@google.com        PhysRegIndex phys_reg = freeList.getCCReg();
81212854Sgabeblack@google.com
81312854Sgabeblack@google.com        renameMap[tid].setEntry(creg,phys_reg);
81412854Sgabeblack@google.com        scoreboard.setReg(phys_reg);
81512854Sgabeblack@google.com    }
81612854Sgabeblack@google.com
81712854Sgabeblack@google.com    //Copy Thread Data Into RegFile
81812854Sgabeblack@google.com    //this->copyFromTC(tid);
81912854Sgabeblack@google.com
82012854Sgabeblack@google.com    //Set PC/NPC/NNPC
82112854Sgabeblack@google.com    pcState(src_tc->pcState(), tid);
82212854Sgabeblack@google.com
82312854Sgabeblack@google.com    src_tc->setStatus(ThreadContext::Active);
82412854Sgabeblack@google.com
82512854Sgabeblack@google.com    activateContext(tid);
82612854Sgabeblack@google.com
82712854Sgabeblack@google.com    //Reset ROB/IQ/LSQ Entries
82812854Sgabeblack@google.com    commit.rob->resetEntries();
82912854Sgabeblack@google.com    iew.resetEntries();
83012854Sgabeblack@google.com}
83112854Sgabeblack@google.com
83212854Sgabeblack@google.comtemplate <class Impl>
83312854Sgabeblack@google.comvoid
83412854Sgabeblack@google.comFullO3CPU<Impl>::removeThread(ThreadID tid)
83512854Sgabeblack@google.com{
83612854Sgabeblack@google.com    DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid);
83712854Sgabeblack@google.com
83812854Sgabeblack@google.com    // Copy Thread Data From RegFile
83912854Sgabeblack@google.com    // If thread is suspended, it might be re-allocated
84012854Sgabeblack@google.com    // this->copyToTC(tid);
84112854Sgabeblack@google.com
84212854Sgabeblack@google.com
84312854Sgabeblack@google.com    // @todo: 2-27-2008: Fix how we free up rename mappings
84412854Sgabeblack@google.com    // here to alleviate the case for double-freeing registers
84512854Sgabeblack@google.com    // in SMT workloads.
84612854Sgabeblack@google.com
84712854Sgabeblack@google.com    // Unbind Int Regs from Rename Map
84812854Sgabeblack@google.com    for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
84912854Sgabeblack@google.com        PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
85012854Sgabeblack@google.com        scoreboard.unsetReg(phys_reg);
85112854Sgabeblack@google.com        freeList.addReg(phys_reg);
85212854Sgabeblack@google.com    }
85312854Sgabeblack@google.com
85412854Sgabeblack@google.com    // Unbind Float Regs from Rename Map
85512854Sgabeblack@google.com    int max_reg = TheISA::FP_Reg_Base + TheISA::NumFloatRegs;
85612854Sgabeblack@google.com    for (int freg = TheISA::FP_Reg_Base; freg < max_reg; freg++) {
85712854Sgabeblack@google.com        PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
85812854Sgabeblack@google.com        scoreboard.unsetReg(phys_reg);
85912854Sgabeblack@google.com        freeList.addReg(phys_reg);
86012854Sgabeblack@google.com    }
86112854Sgabeblack@google.com
86212854Sgabeblack@google.com    // Unbind condition-code Regs from Rename Map
86312854Sgabeblack@google.com    max_reg = TheISA::CC_Reg_Base + TheISA::NumCCRegs;
86412854Sgabeblack@google.com    for (int creg = TheISA::CC_Reg_Base; creg < max_reg; creg++) {
86512854Sgabeblack@google.com        PhysRegIndex phys_reg = renameMap[tid].lookup(creg);
86612854Sgabeblack@google.com        scoreboard.unsetReg(phys_reg);
86712854Sgabeblack@google.com        freeList.addReg(phys_reg);
86812854Sgabeblack@google.com    }
86912854Sgabeblack@google.com
87012854Sgabeblack@google.com    // Squash Throughout Pipeline
87112854Sgabeblack@google.com    DynInstPtr inst = commit.rob->readHeadInst(tid);
87212854Sgabeblack@google.com    InstSeqNum squash_seq_num = inst->seqNum;
87312854Sgabeblack@google.com    fetch.squash(0, squash_seq_num, inst, tid);
87412854Sgabeblack@google.com    decode.squash(tid);
87512854Sgabeblack@google.com    rename.squash(squash_seq_num, tid);
87612854Sgabeblack@google.com    iew.squash(tid);
87712854Sgabeblack@google.com    iew.ldstQueue.squash(squash_seq_num, tid);
87812854Sgabeblack@google.com    commit.rob->squash(squash_seq_num, tid);
87912854Sgabeblack@google.com
88012854Sgabeblack@google.com
88112854Sgabeblack@google.com    assert(iew.instQueue.getCount(tid) == 0);
88212854Sgabeblack@google.com    assert(iew.ldstQueue.getCount(tid) == 0);
88312854Sgabeblack@google.com
88412854Sgabeblack@google.com    // Reset ROB/IQ/LSQ Entries
88512854Sgabeblack@google.com
88612854Sgabeblack@google.com    // Commented out for now.  This should be possible to do by
88712854Sgabeblack@google.com    // telling all the pipeline stages to drain first, and then
88812854Sgabeblack@google.com    // checking until the drain completes.  Once the pipeline is
88912854Sgabeblack@google.com    // drained, call resetEntries(). - 10-09-06 ktlim
89012854Sgabeblack@google.com/*
89112854Sgabeblack@google.com    if (activeThreads.size() >= 1) {
89212854Sgabeblack@google.com        commit.rob->resetEntries();
89312854Sgabeblack@google.com        iew.resetEntries();
89412854Sgabeblack@google.com    }
89512854Sgabeblack@google.com*/
89612854Sgabeblack@google.com}
89712854Sgabeblack@google.com
89812854Sgabeblack@google.comtemplate <class Impl>
89912854Sgabeblack@google.comFault
90012854Sgabeblack@google.comFullO3CPU<Impl>::hwrei(ThreadID tid)
90112854Sgabeblack@google.com{
90212854Sgabeblack@google.com#if THE_ISA == ALPHA_ISA
90312854Sgabeblack@google.com    // Need to clear the lock flag upon returning from an interrupt.
90412854Sgabeblack@google.com    this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid);
90512854Sgabeblack@google.com
90612854Sgabeblack@google.com    this->thread[tid]->kernelStats->hwrei();
90712854Sgabeblack@google.com
90812854Sgabeblack@google.com    // FIXME: XXX check for interrupts? XXX
90912854Sgabeblack@google.com#endif
91012854Sgabeblack@google.com    return NoFault;
91112854Sgabeblack@google.com}
91212854Sgabeblack@google.com
91312854Sgabeblack@google.comtemplate <class Impl>
91412854Sgabeblack@google.combool
91512854Sgabeblack@google.comFullO3CPU<Impl>::simPalCheck(int palFunc, ThreadID tid)
91612854Sgabeblack@google.com{
91712854Sgabeblack@google.com#if THE_ISA == ALPHA_ISA
91812854Sgabeblack@google.com    if (this->thread[tid]->kernelStats)
91912854Sgabeblack@google.com        this->thread[tid]->kernelStats->callpal(palFunc,
92012854Sgabeblack@google.com                                                this->threadContexts[tid]);
92112854Sgabeblack@google.com
92212854Sgabeblack@google.com    switch (palFunc) {
92312854Sgabeblack@google.com      case PAL::halt:
92412854Sgabeblack@google.com        halt();
92512854Sgabeblack@google.com        if (--System::numSystemsRunning == 0)
92612854Sgabeblack@google.com            exitSimLoop("all cpus halted");
92712854Sgabeblack@google.com        break;
92812854Sgabeblack@google.com
92912854Sgabeblack@google.com      case PAL::bpt:
93012854Sgabeblack@google.com      case PAL::bugchk:
93112854Sgabeblack@google.com        if (this->system->breakpoint())
93212854Sgabeblack@google.com            return false;
93312854Sgabeblack@google.com        break;
93412854Sgabeblack@google.com    }
93512854Sgabeblack@google.com#endif
93612854Sgabeblack@google.com    return true;
93712854Sgabeblack@google.com}
93812854Sgabeblack@google.com
93912854Sgabeblack@google.comtemplate <class Impl>
94012854Sgabeblack@google.comFault
94112854Sgabeblack@google.comFullO3CPU<Impl>::getInterrupts()
94212854Sgabeblack@google.com{
94312854Sgabeblack@google.com    // Check if there are any outstanding interrupts
94412854Sgabeblack@google.com    return this->interrupts[0]->getInterrupt(this->threadContexts[0]);
94512854Sgabeblack@google.com}
94612854Sgabeblack@google.com
94712854Sgabeblack@google.comtemplate <class Impl>
94812854Sgabeblack@google.comvoid
94912854Sgabeblack@google.comFullO3CPU<Impl>::processInterrupts(const Fault &interrupt)
95012854Sgabeblack@google.com{
95112854Sgabeblack@google.com    // Check for interrupts here.  For now can copy the code that
95212854Sgabeblack@google.com    // exists within isa_fullsys_traits.hh.  Also assume that thread 0
95312854Sgabeblack@google.com    // is the one that handles the interrupts.
95412854Sgabeblack@google.com    // @todo: Possibly consolidate the interrupt checking code.
95512854Sgabeblack@google.com    // @todo: Allow other threads to handle interrupts.
95612854Sgabeblack@google.com
95712854Sgabeblack@google.com    assert(interrupt != NoFault);
95812854Sgabeblack@google.com    this->interrupts[0]->updateIntrInfo(this->threadContexts[0]);
95912854Sgabeblack@google.com
96012854Sgabeblack@google.com    DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name());
96112854Sgabeblack@google.com    this->trap(interrupt, 0, nullptr);
96212854Sgabeblack@google.com}
96312854Sgabeblack@google.com
96412854Sgabeblack@google.comtemplate <class Impl>
96512854Sgabeblack@google.comvoid
96612854Sgabeblack@google.comFullO3CPU<Impl>::trap(const Fault &fault, ThreadID tid,
96712854Sgabeblack@google.com                      const StaticInstPtr &inst)
96812854Sgabeblack@google.com{
96912854Sgabeblack@google.com    // Pass the thread's TC into the invoke method.
97012854Sgabeblack@google.com    fault->invoke(this->threadContexts[tid], inst);
97112854Sgabeblack@google.com}
97212854Sgabeblack@google.com
97312854Sgabeblack@google.comtemplate <class Impl>
97412854Sgabeblack@google.comvoid
97512854Sgabeblack@google.comFullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid)
97612854Sgabeblack@google.com{
97712854Sgabeblack@google.com    DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
97812854Sgabeblack@google.com
97912854Sgabeblack@google.com    DPRINTF(Activity,"Activity: syscall() called.\n");
98012854Sgabeblack@google.com
98112854Sgabeblack@google.com    // Temporarily increase this by one to account for the syscall
98212854Sgabeblack@google.com    // instruction.
98312854Sgabeblack@google.com    ++(this->thread[tid]->funcExeInst);
98412854Sgabeblack@google.com
98512854Sgabeblack@google.com    // Execute the actual syscall.
98612854Sgabeblack@google.com    this->thread[tid]->syscall(callnum);
98712854Sgabeblack@google.com
98812854Sgabeblack@google.com    // Decrease funcExeInst by one as the normal commit will handle
98912854Sgabeblack@google.com    // incrementing it.
99012854Sgabeblack@google.com    --(this->thread[tid]->funcExeInst);
99112854Sgabeblack@google.com}
99212854Sgabeblack@google.com
99312854Sgabeblack@google.comtemplate <class Impl>
99412854Sgabeblack@google.comvoid
99512854Sgabeblack@google.comFullO3CPU<Impl>::serializeThread(CheckpointOut &cp, ThreadID tid) const
99612854Sgabeblack@google.com{
99712854Sgabeblack@google.com    thread[tid]->serialize(cp);
99812854Sgabeblack@google.com}
99912854Sgabeblack@google.com
100012854Sgabeblack@google.comtemplate <class Impl>
100112854Sgabeblack@google.comvoid
100212854Sgabeblack@google.comFullO3CPU<Impl>::unserializeThread(CheckpointIn &cp, ThreadID tid)
100312854Sgabeblack@google.com{
100412854Sgabeblack@google.com    thread[tid]->unserialize(cp);
100512854Sgabeblack@google.com}
100612854Sgabeblack@google.com
100712854Sgabeblack@google.comtemplate <class Impl>
100812854Sgabeblack@google.comDrainState
100912854Sgabeblack@google.comFullO3CPU<Impl>::drain()
101012854Sgabeblack@google.com{
101112854Sgabeblack@google.com    // If the CPU isn't doing anything, then return immediately.
101212854Sgabeblack@google.com    if (switchedOut())
101312854Sgabeblack@google.com        return DrainState::Drained;
101412854Sgabeblack@google.com
101512854Sgabeblack@google.com    DPRINTF(Drain, "Draining...\n");
101612854Sgabeblack@google.com
101712854Sgabeblack@google.com    // We only need to signal a drain to the commit stage as this
101812854Sgabeblack@google.com    // initiates squashing controls the draining. Once the commit
101912854Sgabeblack@google.com    // stage commits an instruction where it is safe to stop, it'll
102012854Sgabeblack@google.com    // squash the rest of the instructions in the pipeline and force
102112854Sgabeblack@google.com    // the fetch stage to stall. The pipeline will be drained once all
102212854Sgabeblack@google.com    // in-flight instructions have retired.
102312854Sgabeblack@google.com    commit.drain();
102412854Sgabeblack@google.com
102512854Sgabeblack@google.com    // Wake the CPU and record activity so everything can drain out if
102612854Sgabeblack@google.com    // the CPU was not able to immediately drain.
102712854Sgabeblack@google.com    if (!isDrained())  {
102812854Sgabeblack@google.com        wakeCPU();
102912854Sgabeblack@google.com        activityRec.activity();
103012854Sgabeblack@google.com
103112854Sgabeblack@google.com        DPRINTF(Drain, "CPU not drained\n");
103212854Sgabeblack@google.com
103312854Sgabeblack@google.com        return DrainState::Draining;
103412854Sgabeblack@google.com    } else {
103512854Sgabeblack@google.com        DPRINTF(Drain, "CPU is already drained\n");
103612854Sgabeblack@google.com        if (tickEvent.scheduled())
103712854Sgabeblack@google.com            deschedule(tickEvent);
103812854Sgabeblack@google.com
103912854Sgabeblack@google.com        // Flush out any old data from the time buffers.  In
104012854Sgabeblack@google.com        // particular, there might be some data in flight from the
104112854Sgabeblack@google.com        // fetch stage that isn't visible in any of the CPU buffers we
104212854Sgabeblack@google.com        // test in isDrained().
104312854Sgabeblack@google.com        for (int i = 0; i < timeBuffer.getSize(); ++i) {
104412854Sgabeblack@google.com            timeBuffer.advance();
104512854Sgabeblack@google.com            fetchQueue.advance();
104612854Sgabeblack@google.com            decodeQueue.advance();
104712854Sgabeblack@google.com            renameQueue.advance();
104812854Sgabeblack@google.com            iewQueue.advance();
104912854Sgabeblack@google.com        }
105012854Sgabeblack@google.com
105112854Sgabeblack@google.com        drainSanityCheck();
105212854Sgabeblack@google.com        return DrainState::Drained;
105312854Sgabeblack@google.com    }
105412854Sgabeblack@google.com}
105512854Sgabeblack@google.com
105612854Sgabeblack@google.comtemplate <class Impl>
105712854Sgabeblack@google.combool
105812854Sgabeblack@google.comFullO3CPU<Impl>::tryDrain()
105912854Sgabeblack@google.com{
106012854Sgabeblack@google.com    if (drainState() != DrainState::Draining || !isDrained())
106112854Sgabeblack@google.com        return false;
106212854Sgabeblack@google.com
106312854Sgabeblack@google.com    if (tickEvent.scheduled())
106412854Sgabeblack@google.com        deschedule(tickEvent);
106512854Sgabeblack@google.com
106612854Sgabeblack@google.com    DPRINTF(Drain, "CPU done draining, processing drain event\n");
106712854Sgabeblack@google.com    signalDrainDone();
106812854Sgabeblack@google.com
106912854Sgabeblack@google.com    return true;
107012854Sgabeblack@google.com}
107112854Sgabeblack@google.com
107212854Sgabeblack@google.comtemplate <class Impl>
107312854Sgabeblack@google.comvoid
107412854Sgabeblack@google.comFullO3CPU<Impl>::drainSanityCheck() const
107512854Sgabeblack@google.com{
107612854Sgabeblack@google.com    assert(isDrained());
107712854Sgabeblack@google.com    fetch.drainSanityCheck();
107812854Sgabeblack@google.com    decode.drainSanityCheck();
107912854Sgabeblack@google.com    rename.drainSanityCheck();
108012854Sgabeblack@google.com    iew.drainSanityCheck();
108112854Sgabeblack@google.com    commit.drainSanityCheck();
108212854Sgabeblack@google.com}
108312854Sgabeblack@google.com
108412854Sgabeblack@google.comtemplate <class Impl>
108512854Sgabeblack@google.combool
108612854Sgabeblack@google.comFullO3CPU<Impl>::isDrained() const
108712854Sgabeblack@google.com{
108812854Sgabeblack@google.com    bool drained(true);
108912854Sgabeblack@google.com
109012854Sgabeblack@google.com    if (!instList.empty() || !removeList.empty()) {
109112854Sgabeblack@google.com        DPRINTF(Drain, "Main CPU structures not drained.\n");
109212854Sgabeblack@google.com        drained = false;
109312854Sgabeblack@google.com    }
109412854Sgabeblack@google.com
109512854Sgabeblack@google.com    if (!fetch.isDrained()) {
109612854Sgabeblack@google.com        DPRINTF(Drain, "Fetch not drained.\n");
109712854Sgabeblack@google.com        drained = false;
109812854Sgabeblack@google.com    }
109912854Sgabeblack@google.com
110012854Sgabeblack@google.com    if (!decode.isDrained()) {
110112854Sgabeblack@google.com        DPRINTF(Drain, "Decode not drained.\n");
110212854Sgabeblack@google.com        drained = false;
110312854Sgabeblack@google.com    }
110412854Sgabeblack@google.com
110512854Sgabeblack@google.com    if (!rename.isDrained()) {
110612854Sgabeblack@google.com        DPRINTF(Drain, "Rename not drained.\n");
110712854Sgabeblack@google.com        drained = false;
110812854Sgabeblack@google.com    }
110912854Sgabeblack@google.com
111012854Sgabeblack@google.com    if (!iew.isDrained()) {
111112854Sgabeblack@google.com        DPRINTF(Drain, "IEW not drained.\n");
111212854Sgabeblack@google.com        drained = false;
111312854Sgabeblack@google.com    }
111412854Sgabeblack@google.com
111512854Sgabeblack@google.com    if (!commit.isDrained()) {
111612854Sgabeblack@google.com        DPRINTF(Drain, "Commit not drained.\n");
111712854Sgabeblack@google.com        drained = false;
111812854Sgabeblack@google.com    }
111912854Sgabeblack@google.com
112012854Sgabeblack@google.com    return drained;
112112854Sgabeblack@google.com}
112212854Sgabeblack@google.com
112312854Sgabeblack@google.comtemplate <class Impl>
112412854Sgabeblack@google.comvoid
112512854Sgabeblack@google.comFullO3CPU<Impl>::commitDrained(ThreadID tid)
112612854Sgabeblack@google.com{
112712854Sgabeblack@google.com    fetch.drainStall(tid);
112812854Sgabeblack@google.com}
112912854Sgabeblack@google.com
113012854Sgabeblack@google.comtemplate <class Impl>
113112854Sgabeblack@google.comvoid
113212854Sgabeblack@google.comFullO3CPU<Impl>::drainResume()
113312854Sgabeblack@google.com{
113412854Sgabeblack@google.com    if (switchedOut())
113512854Sgabeblack@google.com        return;
113612854Sgabeblack@google.com
113712854Sgabeblack@google.com    DPRINTF(Drain, "Resuming...\n");
113812854Sgabeblack@google.com    verifyMemoryMode();
113912854Sgabeblack@google.com
114012854Sgabeblack@google.com    fetch.drainResume();
114112854Sgabeblack@google.com    commit.drainResume();
114212854Sgabeblack@google.com
114312854Sgabeblack@google.com    _status = Idle;
114412854Sgabeblack@google.com    for (ThreadID i = 0; i < thread.size(); i++) {
114512854Sgabeblack@google.com        if (thread[i]->status() == ThreadContext::Active) {
114612854Sgabeblack@google.com            DPRINTF(Drain, "Activating thread: %i\n", i);
114712854Sgabeblack@google.com            activateThread(i);
114812854Sgabeblack@google.com            _status = Running;
114912854Sgabeblack@google.com        }
115012854Sgabeblack@google.com    }
115112854Sgabeblack@google.com
115212854Sgabeblack@google.com    assert(!tickEvent.scheduled());
115312854Sgabeblack@google.com    if (_status == Running)
115412854Sgabeblack@google.com        schedule(tickEvent, nextCycle());
115512854Sgabeblack@google.com}
115612854Sgabeblack@google.com
115712854Sgabeblack@google.comtemplate <class Impl>
115812854Sgabeblack@google.comvoid
115912854Sgabeblack@google.comFullO3CPU<Impl>::switchOut()
116012854Sgabeblack@google.com{
116112854Sgabeblack@google.com    DPRINTF(O3CPU, "Switching out\n");
116212854Sgabeblack@google.com    BaseCPU::switchOut();
116312854Sgabeblack@google.com
116412854Sgabeblack@google.com    activityRec.reset();
116512854Sgabeblack@google.com
116612854Sgabeblack@google.com    _status = SwitchedOut;
116712854Sgabeblack@google.com
116812854Sgabeblack@google.com    if (checker)
116912854Sgabeblack@google.com        checker->switchOut();
117012854Sgabeblack@google.com}
117112854Sgabeblack@google.com
117212854Sgabeblack@google.comtemplate <class Impl>
117312854Sgabeblack@google.comvoid
117412854Sgabeblack@google.comFullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
117512854Sgabeblack@google.com{
117612854Sgabeblack@google.com    BaseCPU::takeOverFrom(oldCPU);
117712854Sgabeblack@google.com
117812854Sgabeblack@google.com    fetch.takeOverFrom();
117912854Sgabeblack@google.com    decode.takeOverFrom();
118012854Sgabeblack@google.com    rename.takeOverFrom();
118112854Sgabeblack@google.com    iew.takeOverFrom();
118212854Sgabeblack@google.com    commit.takeOverFrom();
118312854Sgabeblack@google.com
118412854Sgabeblack@google.com    assert(!tickEvent.scheduled());
118512854Sgabeblack@google.com
118612854Sgabeblack@google.com    FullO3CPU<Impl> *oldO3CPU = dynamic_cast<FullO3CPU<Impl>*>(oldCPU);
118712854Sgabeblack@google.com    if (oldO3CPU)
118812854Sgabeblack@google.com        globalSeqNum = oldO3CPU->globalSeqNum;
118912854Sgabeblack@google.com
119012854Sgabeblack@google.com    lastRunningCycle = curCycle();
119112854Sgabeblack@google.com    _status = Idle;
119212854Sgabeblack@google.com}
119312854Sgabeblack@google.com
119412854Sgabeblack@google.comtemplate <class Impl>
119512854Sgabeblack@google.comvoid
119612854Sgabeblack@google.comFullO3CPU<Impl>::verifyMemoryMode() const
119712854Sgabeblack@google.com{
119812854Sgabeblack@google.com    if (!system->isTimingMode()) {
119912854Sgabeblack@google.com        fatal("The O3 CPU requires the memory system to be in "
120012854Sgabeblack@google.com              "'timing' mode.\n");
120112854Sgabeblack@google.com    }
120212854Sgabeblack@google.com}
120312854Sgabeblack@google.com
120412854Sgabeblack@google.comtemplate <class Impl>
120512854Sgabeblack@google.comTheISA::MiscReg
120612854Sgabeblack@google.comFullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid) const
120712854Sgabeblack@google.com{
120812854Sgabeblack@google.com    return this->isa[tid]->readMiscRegNoEffect(misc_reg);
120912854Sgabeblack@google.com}
121012854Sgabeblack@google.com
121112854Sgabeblack@google.comtemplate <class Impl>
121212854Sgabeblack@google.comTheISA::MiscReg
121312854Sgabeblack@google.comFullO3CPU<Impl>::readMiscReg(int misc_reg, ThreadID tid)
121412854Sgabeblack@google.com{
121512854Sgabeblack@google.com    miscRegfileReads++;
121612854Sgabeblack@google.com    return this->isa[tid]->readMiscReg(misc_reg, tcBase(tid));
121712854Sgabeblack@google.com}
121812854Sgabeblack@google.com
121912854Sgabeblack@google.comtemplate <class Impl>
122012854Sgabeblack@google.comvoid
122112854Sgabeblack@google.comFullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg,
122212854Sgabeblack@google.com        const TheISA::MiscReg &val, ThreadID tid)
122312854Sgabeblack@google.com{
122412854Sgabeblack@google.com    this->isa[tid]->setMiscRegNoEffect(misc_reg, val);
122512854Sgabeblack@google.com}
122612854Sgabeblack@google.com
122712854Sgabeblack@google.comtemplate <class Impl>
122812854Sgabeblack@google.comvoid
122912854Sgabeblack@google.comFullO3CPU<Impl>::setMiscReg(int misc_reg,
123012854Sgabeblack@google.com        const TheISA::MiscReg &val, ThreadID tid)
123112854Sgabeblack@google.com{
123212854Sgabeblack@google.com    miscRegfileWrites++;
123312854Sgabeblack@google.com    this->isa[tid]->setMiscReg(misc_reg, val, tcBase(tid));
123412854Sgabeblack@google.com}
123512854Sgabeblack@google.com
123612854Sgabeblack@google.comtemplate <class Impl>
123712854Sgabeblack@google.comuint64_t
123812854Sgabeblack@google.comFullO3CPU<Impl>::readIntReg(int reg_idx)
123912854Sgabeblack@google.com{
124012854Sgabeblack@google.com    intRegfileReads++;
124112854Sgabeblack@google.com    return regFile.readIntReg(reg_idx);
124212854Sgabeblack@google.com}
124312854Sgabeblack@google.com
124412854Sgabeblack@google.comtemplate <class Impl>
124512854Sgabeblack@google.comFloatReg
124612854Sgabeblack@google.comFullO3CPU<Impl>::readFloatReg(int reg_idx)
124712854Sgabeblack@google.com{
124812854Sgabeblack@google.com    fpRegfileReads++;
124912854Sgabeblack@google.com    return regFile.readFloatReg(reg_idx);
125012854Sgabeblack@google.com}
125112854Sgabeblack@google.com
125212854Sgabeblack@google.comtemplate <class Impl>
125312854Sgabeblack@google.comFloatRegBits
125412854Sgabeblack@google.comFullO3CPU<Impl>::readFloatRegBits(int reg_idx)
125512854Sgabeblack@google.com{
125612854Sgabeblack@google.com    fpRegfileReads++;
125712854Sgabeblack@google.com    return regFile.readFloatRegBits(reg_idx);
125812854Sgabeblack@google.com}
125912854Sgabeblack@google.com
126012854Sgabeblack@google.comtemplate <class Impl>
126112854Sgabeblack@google.comCCReg
126212854Sgabeblack@google.comFullO3CPU<Impl>::readCCReg(int reg_idx)
126312854Sgabeblack@google.com{
126412854Sgabeblack@google.com    ccRegfileReads++;
126512854Sgabeblack@google.com    return regFile.readCCReg(reg_idx);
126612854Sgabeblack@google.com}
126712854Sgabeblack@google.com
126812854Sgabeblack@google.comtemplate <class Impl>
126912854Sgabeblack@google.comvoid
127012854Sgabeblack@google.comFullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
127112854Sgabeblack@google.com{
127212854Sgabeblack@google.com    intRegfileWrites++;
127312854Sgabeblack@google.com    regFile.setIntReg(reg_idx, val);
127412854Sgabeblack@google.com}
127512854Sgabeblack@google.com
127612854Sgabeblack@google.comtemplate <class Impl>
127712854Sgabeblack@google.comvoid
127812854Sgabeblack@google.comFullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val)
127912854Sgabeblack@google.com{
128012854Sgabeblack@google.com    fpRegfileWrites++;
128112854Sgabeblack@google.com    regFile.setFloatReg(reg_idx, val);
128212854Sgabeblack@google.com}
128312854Sgabeblack@google.com
128412854Sgabeblack@google.comtemplate <class Impl>
128512854Sgabeblack@google.comvoid
128612854Sgabeblack@google.comFullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
128712854Sgabeblack@google.com{
128812854Sgabeblack@google.com    fpRegfileWrites++;
128912854Sgabeblack@google.com    regFile.setFloatRegBits(reg_idx, val);
129012854Sgabeblack@google.com}
129112854Sgabeblack@google.com
129212854Sgabeblack@google.comtemplate <class Impl>
129312854Sgabeblack@google.comvoid
129412854Sgabeblack@google.comFullO3CPU<Impl>::setCCReg(int reg_idx, CCReg val)
129512854Sgabeblack@google.com{
129612854Sgabeblack@google.com    ccRegfileWrites++;
129712854Sgabeblack@google.com    regFile.setCCReg(reg_idx, val);
129812854Sgabeblack@google.com}
129912854Sgabeblack@google.com
130012854Sgabeblack@google.comtemplate <class Impl>
130112854Sgabeblack@google.comuint64_t
130212854Sgabeblack@google.comFullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid)
130312854Sgabeblack@google.com{
130412854Sgabeblack@google.com    intRegfileReads++;
130512854Sgabeblack@google.com    PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx);
130612854Sgabeblack@google.com
130712854Sgabeblack@google.com    return regFile.readIntReg(phys_reg);
130812854Sgabeblack@google.com}
130912854Sgabeblack@google.com
131012854Sgabeblack@google.comtemplate <class Impl>
131112854Sgabeblack@google.comfloat
131212854Sgabeblack@google.comFullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid)
131312854Sgabeblack@google.com{
131412854Sgabeblack@google.com    fpRegfileReads++;
131512854Sgabeblack@google.com    PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
131612854Sgabeblack@google.com
131712854Sgabeblack@google.com    return regFile.readFloatReg(phys_reg);
131812854Sgabeblack@google.com}
131912854Sgabeblack@google.com
132012854Sgabeblack@google.comtemplate <class Impl>
132112854Sgabeblack@google.comuint64_t
132212854Sgabeblack@google.comFullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid)
132312854Sgabeblack@google.com{
132412854Sgabeblack@google.com    fpRegfileReads++;
132512854Sgabeblack@google.com    PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
132612854Sgabeblack@google.com
132712854Sgabeblack@google.com    return regFile.readFloatRegBits(phys_reg);
132812854Sgabeblack@google.com}
132912854Sgabeblack@google.com
133012854Sgabeblack@google.comtemplate <class Impl>
133112854Sgabeblack@google.comCCReg
133212854Sgabeblack@google.comFullO3CPU<Impl>::readArchCCReg(int reg_idx, ThreadID tid)
133312854Sgabeblack@google.com{
133412854Sgabeblack@google.com    ccRegfileReads++;
133512854Sgabeblack@google.com    PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx);
133612854Sgabeblack@google.com
133712854Sgabeblack@google.com    return regFile.readCCReg(phys_reg);
133812854Sgabeblack@google.com}
133912854Sgabeblack@google.com
134012854Sgabeblack@google.comtemplate <class Impl>
134112854Sgabeblack@google.comvoid
134212854Sgabeblack@google.comFullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid)
134312854Sgabeblack@google.com{
134412854Sgabeblack@google.com    intRegfileWrites++;
134512854Sgabeblack@google.com    PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx);
134612854Sgabeblack@google.com
134712854Sgabeblack@google.com    regFile.setIntReg(phys_reg, val);
134812854Sgabeblack@google.com}
134912854Sgabeblack@google.com
135012854Sgabeblack@google.comtemplate <class Impl>
135112854Sgabeblack@google.comvoid
135212854Sgabeblack@google.comFullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid)
135312854Sgabeblack@google.com{
135412854Sgabeblack@google.com    fpRegfileWrites++;
135512854Sgabeblack@google.com    PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
135612854Sgabeblack@google.com
135712854Sgabeblack@google.com    regFile.setFloatReg(phys_reg, val);
135812854Sgabeblack@google.com}
135912854Sgabeblack@google.com
136012854Sgabeblack@google.comtemplate <class Impl>
136112854Sgabeblack@google.comvoid
136212854Sgabeblack@google.comFullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid)
136312854Sgabeblack@google.com{
136412854Sgabeblack@google.com    fpRegfileWrites++;
136512854Sgabeblack@google.com    PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
136612854Sgabeblack@google.com
136712854Sgabeblack@google.com    regFile.setFloatRegBits(phys_reg, val);
136812854Sgabeblack@google.com}
136912854Sgabeblack@google.com
137012854Sgabeblack@google.comtemplate <class Impl>
137112854Sgabeblack@google.comvoid
137212854Sgabeblack@google.comFullO3CPU<Impl>::setArchCCReg(int reg_idx, CCReg val, ThreadID tid)
137312854Sgabeblack@google.com{
137412854Sgabeblack@google.com    ccRegfileWrites++;
137512854Sgabeblack@google.com    PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx);
137612854Sgabeblack@google.com
137712854Sgabeblack@google.com    regFile.setCCReg(phys_reg, val);
137812854Sgabeblack@google.com}
137912854Sgabeblack@google.com
138012854Sgabeblack@google.comtemplate <class Impl>
138112854Sgabeblack@google.comTheISA::PCState
138212854Sgabeblack@google.comFullO3CPU<Impl>::pcState(ThreadID tid)
138312854Sgabeblack@google.com{
138412854Sgabeblack@google.com    return commit.pcState(tid);
138512854Sgabeblack@google.com}
138612854Sgabeblack@google.com
138712854Sgabeblack@google.comtemplate <class Impl>
138812854Sgabeblack@google.comvoid
138912854Sgabeblack@google.comFullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid)
139012854Sgabeblack@google.com{
139112854Sgabeblack@google.com    commit.pcState(val, tid);
139212854Sgabeblack@google.com}
139312854Sgabeblack@google.com
139412854Sgabeblack@google.comtemplate <class Impl>
139512854Sgabeblack@google.comAddr
139612854Sgabeblack@google.comFullO3CPU<Impl>::instAddr(ThreadID tid)
139712854Sgabeblack@google.com{
139812854Sgabeblack@google.com    return commit.instAddr(tid);
139912854Sgabeblack@google.com}
140012854Sgabeblack@google.com
140112854Sgabeblack@google.comtemplate <class Impl>
140212854Sgabeblack@google.comAddr
140312854Sgabeblack@google.comFullO3CPU<Impl>::nextInstAddr(ThreadID tid)
140412854Sgabeblack@google.com{
140512854Sgabeblack@google.com    return commit.nextInstAddr(tid);
140612854Sgabeblack@google.com}
140712854Sgabeblack@google.com
140812854Sgabeblack@google.comtemplate <class Impl>
140912854Sgabeblack@google.comMicroPC
141012854Sgabeblack@google.comFullO3CPU<Impl>::microPC(ThreadID tid)
141112854Sgabeblack@google.com{
141212854Sgabeblack@google.com    return commit.microPC(tid);
141312854Sgabeblack@google.com}
141412854Sgabeblack@google.com
141512854Sgabeblack@google.comtemplate <class Impl>
141612854Sgabeblack@google.comvoid
141712854Sgabeblack@google.comFullO3CPU<Impl>::squashFromTC(ThreadID tid)
141812854Sgabeblack@google.com{
141912854Sgabeblack@google.com    this->thread[tid]->noSquashFromTC = true;
142012854Sgabeblack@google.com    this->commit.generateTCEvent(tid);
142112854Sgabeblack@google.com}
142212854Sgabeblack@google.com
142312854Sgabeblack@google.comtemplate <class Impl>
142412854Sgabeblack@google.comtypename FullO3CPU<Impl>::ListIt
142512854Sgabeblack@google.comFullO3CPU<Impl>::addInst(DynInstPtr &inst)
142612854Sgabeblack@google.com{
142712854Sgabeblack@google.com    instList.push_back(inst);
142812854Sgabeblack@google.com
142912854Sgabeblack@google.com    return --(instList.end());
143012854Sgabeblack@google.com}
143112854Sgabeblack@google.com
143212854Sgabeblack@google.comtemplate <class Impl>
143312854Sgabeblack@google.comvoid
143412854Sgabeblack@google.comFullO3CPU<Impl>::instDone(ThreadID tid, DynInstPtr &inst)
143512854Sgabeblack@google.com{
143612854Sgabeblack@google.com    // Keep an instruction count.
143712854Sgabeblack@google.com    if (!inst->isMicroop() || inst->isLastMicroop()) {
143812854Sgabeblack@google.com        thread[tid]->numInst++;
143912854Sgabeblack@google.com        thread[tid]->numInsts++;
144012854Sgabeblack@google.com        committedInsts[tid]++;
144112854Sgabeblack@google.com        system->totalNumInsts++;
144212854Sgabeblack@google.com
144312854Sgabeblack@google.com        // Check for instruction-count-based events.
144412854Sgabeblack@google.com        comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
144512854Sgabeblack@google.com        system->instEventQueue.serviceEvents(system->totalNumInsts);
144612854Sgabeblack@google.com    }
144712854Sgabeblack@google.com    thread[tid]->numOp++;
144812854Sgabeblack@google.com    thread[tid]->numOps++;
144912854Sgabeblack@google.com    committedOps[tid]++;
145012854Sgabeblack@google.com
145112854Sgabeblack@google.com    probeInstCommit(inst->staticInst);
145212854Sgabeblack@google.com}
145312854Sgabeblack@google.com
145412854Sgabeblack@google.comtemplate <class Impl>
145512854Sgabeblack@google.comvoid
145612854Sgabeblack@google.comFullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
145712854Sgabeblack@google.com{
145812854Sgabeblack@google.com    DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s "
145912854Sgabeblack@google.com            "[sn:%lli]\n",
146012854Sgabeblack@google.com            inst->threadNumber, inst->pcState(), inst->seqNum);
146112854Sgabeblack@google.com
146212854Sgabeblack@google.com    removeInstsThisCycle = true;
146312854Sgabeblack@google.com
146412854Sgabeblack@google.com    // Remove the front instruction.
146512854Sgabeblack@google.com    removeList.push(inst->getInstListIt());
146612854Sgabeblack@google.com}
146712854Sgabeblack@google.com
146812854Sgabeblack@google.comtemplate <class Impl>
146912854Sgabeblack@google.comvoid
147012854Sgabeblack@google.comFullO3CPU<Impl>::removeInstsNotInROB(ThreadID tid)
147112854Sgabeblack@google.com{
147212854Sgabeblack@google.com    DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction"
147312854Sgabeblack@google.com            " list.\n", tid);
147412854Sgabeblack@google.com
147512854Sgabeblack@google.com    ListIt end_it;
147612854Sgabeblack@google.com
147712854Sgabeblack@google.com    bool rob_empty = false;
147812854Sgabeblack@google.com
147912854Sgabeblack@google.com    if (instList.empty()) {
148012854Sgabeblack@google.com        return;
148112854Sgabeblack@google.com    } else if (rob.isEmpty(tid)) {
148212854Sgabeblack@google.com        DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n");
148312854Sgabeblack@google.com        end_it = instList.begin();
148412854Sgabeblack@google.com        rob_empty = true;
148512854Sgabeblack@google.com    } else {
148612854Sgabeblack@google.com        end_it = (rob.readTailInst(tid))->getInstListIt();
148712854Sgabeblack@google.com        DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n");
148812854Sgabeblack@google.com    }
148912854Sgabeblack@google.com
149012854Sgabeblack@google.com    removeInstsThisCycle = true;
149112854Sgabeblack@google.com
149212854Sgabeblack@google.com    ListIt inst_it = instList.end();
149312854Sgabeblack@google.com
149412854Sgabeblack@google.com    inst_it--;
149512854Sgabeblack@google.com
149612854Sgabeblack@google.com    // Walk through the instruction list, removing any instructions
149712854Sgabeblack@google.com    // that were inserted after the given instruction iterator, end_it.
149812854Sgabeblack@google.com    while (inst_it != end_it) {
149912854Sgabeblack@google.com        assert(!instList.empty());
150012854Sgabeblack@google.com
150112854Sgabeblack@google.com        squashInstIt(inst_it, tid);
150212854Sgabeblack@google.com
150312854Sgabeblack@google.com        inst_it--;
150412854Sgabeblack@google.com    }
150512854Sgabeblack@google.com
150612854Sgabeblack@google.com    // If the ROB was empty, then we actually need to remove the first
150712854Sgabeblack@google.com    // instruction as well.
150812854Sgabeblack@google.com    if (rob_empty) {
150912854Sgabeblack@google.com        squashInstIt(inst_it, tid);
151012854Sgabeblack@google.com    }
151112854Sgabeblack@google.com}
151212854Sgabeblack@google.com
151312854Sgabeblack@google.comtemplate <class Impl>
151412854Sgabeblack@google.comvoid
151512854Sgabeblack@google.comFullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid)
151612854Sgabeblack@google.com{
151712854Sgabeblack@google.com    assert(!instList.empty());
151812854Sgabeblack@google.com
151912854Sgabeblack@google.com    removeInstsThisCycle = true;
152012854Sgabeblack@google.com
152112854Sgabeblack@google.com    ListIt inst_iter = instList.end();
152212854Sgabeblack@google.com
152312854Sgabeblack@google.com    inst_iter--;
152412854Sgabeblack@google.com
152512854Sgabeblack@google.com    DPRINTF(O3CPU, "Deleting instructions from instruction "
152612854Sgabeblack@google.com            "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
152712854Sgabeblack@google.com            tid, seq_num, (*inst_iter)->seqNum);
152812854Sgabeblack@google.com
152912854Sgabeblack@google.com    while ((*inst_iter)->seqNum > seq_num) {
153012854Sgabeblack@google.com
153112854Sgabeblack@google.com        bool break_loop = (inst_iter == instList.begin());
153212854Sgabeblack@google.com
153312854Sgabeblack@google.com        squashInstIt(inst_iter, tid);
153412854Sgabeblack@google.com
153512854Sgabeblack@google.com        inst_iter--;
153612854Sgabeblack@google.com
153712854Sgabeblack@google.com        if (break_loop)
153812854Sgabeblack@google.com            break;
153912854Sgabeblack@google.com    }
154012854Sgabeblack@google.com}
154112854Sgabeblack@google.com
154212854Sgabeblack@google.comtemplate <class Impl>
154312854Sgabeblack@google.cominline void
154412854Sgabeblack@google.comFullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid)
154512854Sgabeblack@google.com{
154612854Sgabeblack@google.com    if ((*instIt)->threadNumber == tid) {
154712854Sgabeblack@google.com        DPRINTF(O3CPU, "Squashing instruction, "
154812854Sgabeblack@google.com                "[tid:%i] [sn:%lli] PC %s\n",
154912854Sgabeblack@google.com                (*instIt)->threadNumber,
155012854Sgabeblack@google.com                (*instIt)->seqNum,
155112854Sgabeblack@google.com                (*instIt)->pcState());
155212854Sgabeblack@google.com
155312854Sgabeblack@google.com        // Mark it as squashed.
155412854Sgabeblack@google.com        (*instIt)->setSquashed();
155512854Sgabeblack@google.com
155612854Sgabeblack@google.com        // @todo: Formulate a consistent method for deleting
155712854Sgabeblack@google.com        // instructions from the instruction list
155812854Sgabeblack@google.com        // Remove the instruction from the list.
155912854Sgabeblack@google.com        removeList.push(instIt);
156012854Sgabeblack@google.com    }
156112854Sgabeblack@google.com}
156212854Sgabeblack@google.com
156312854Sgabeblack@google.comtemplate <class Impl>
156412854Sgabeblack@google.comvoid
156512854Sgabeblack@google.comFullO3CPU<Impl>::cleanUpRemovedInsts()
156612854Sgabeblack@google.com{
156712854Sgabeblack@google.com    while (!removeList.empty()) {
156812854Sgabeblack@google.com        DPRINTF(O3CPU, "Removing instruction, "
156912854Sgabeblack@google.com                "[tid:%i] [sn:%lli] PC %s\n",
157012854Sgabeblack@google.com                (*removeList.front())->threadNumber,
157112854Sgabeblack@google.com                (*removeList.front())->seqNum,
157212854Sgabeblack@google.com                (*removeList.front())->pcState());
157312854Sgabeblack@google.com
157412854Sgabeblack@google.com        instList.erase(removeList.front());
157512854Sgabeblack@google.com
157612854Sgabeblack@google.com        removeList.pop();
157712854Sgabeblack@google.com    }
157812854Sgabeblack@google.com
157912854Sgabeblack@google.com    removeInstsThisCycle = false;
158012854Sgabeblack@google.com}
158112854Sgabeblack@google.com/*
158212854Sgabeblack@google.comtemplate <class Impl>
158312854Sgabeblack@google.comvoid
158412854Sgabeblack@google.comFullO3CPU<Impl>::removeAllInsts()
158512854Sgabeblack@google.com{
158612854Sgabeblack@google.com    instList.clear();
158712854Sgabeblack@google.com}
158812854Sgabeblack@google.com*/
158912854Sgabeblack@google.comtemplate <class Impl>
159012854Sgabeblack@google.comvoid
159112854Sgabeblack@google.comFullO3CPU<Impl>::dumpInsts()
159212854Sgabeblack@google.com{
159312854Sgabeblack@google.com    int num = 0;
159412854Sgabeblack@google.com
159512854Sgabeblack@google.com    ListIt inst_list_it = instList.begin();
159612854Sgabeblack@google.com
159712854Sgabeblack@google.com    cprintf("Dumping Instruction List\n");
159812854Sgabeblack@google.com
159912854Sgabeblack@google.com    while (inst_list_it != instList.end()) {
160012854Sgabeblack@google.com        cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
160112854Sgabeblack@google.com                "Squashed:%i\n\n",
160212854Sgabeblack@google.com                num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber,
160312854Sgabeblack@google.com                (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
160412854Sgabeblack@google.com                (*inst_list_it)->isSquashed());
160512854Sgabeblack@google.com        inst_list_it++;
160612854Sgabeblack@google.com        ++num;
160712854Sgabeblack@google.com    }
160812854Sgabeblack@google.com}
160912854Sgabeblack@google.com/*
161012854Sgabeblack@google.comtemplate <class Impl>
161112854Sgabeblack@google.comvoid
161212854Sgabeblack@google.comFullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
161312854Sgabeblack@google.com{
161412854Sgabeblack@google.com    iew.wakeDependents(inst);
161512854Sgabeblack@google.com}
161612854Sgabeblack@google.com*/
161712854Sgabeblack@google.comtemplate <class Impl>
161812854Sgabeblack@google.comvoid
161912854Sgabeblack@google.comFullO3CPU<Impl>::wakeCPU()
162012854Sgabeblack@google.com{
162112854Sgabeblack@google.com    if (activityRec.active() || tickEvent.scheduled()) {
162212854Sgabeblack@google.com        DPRINTF(Activity, "CPU already running.\n");
162312854Sgabeblack@google.com        return;
162412854Sgabeblack@google.com    }
162512854Sgabeblack@google.com
162612854Sgabeblack@google.com    DPRINTF(Activity, "Waking up CPU\n");
162712854Sgabeblack@google.com
162812854Sgabeblack@google.com    Cycles cycles(curCycle() - lastRunningCycle);
162912854Sgabeblack@google.com    // @todo: This is an oddity that is only here to match the stats
163012854Sgabeblack@google.com    if (cycles > 1) {
163112854Sgabeblack@google.com        --cycles;
163212854Sgabeblack@google.com        idleCycles += cycles;
163312854Sgabeblack@google.com        numCycles += cycles;
163412854Sgabeblack@google.com        ppCycles->notify(cycles);
163512854Sgabeblack@google.com    }
163612854Sgabeblack@google.com
163712854Sgabeblack@google.com    schedule(tickEvent, clockEdge());
163812854Sgabeblack@google.com}
163912854Sgabeblack@google.com
164012854Sgabeblack@google.comtemplate <class Impl>
164112854Sgabeblack@google.comvoid
164212854Sgabeblack@google.comFullO3CPU<Impl>::wakeup(ThreadID tid)
164312854Sgabeblack@google.com{
164412854Sgabeblack@google.com    if (this->thread[tid]->status() != ThreadContext::Suspended)
164512854Sgabeblack@google.com        return;
164612854Sgabeblack@google.com
164712854Sgabeblack@google.com    this->wakeCPU();
164812854Sgabeblack@google.com
164912854Sgabeblack@google.com    DPRINTF(Quiesce, "Suspended Processor woken\n");
165012854Sgabeblack@google.com    this->threadContexts[tid]->activate();
165112854Sgabeblack@google.com}
165212854Sgabeblack@google.com
165312854Sgabeblack@google.comtemplate <class Impl>
165412854Sgabeblack@google.comThreadID
165512854Sgabeblack@google.comFullO3CPU<Impl>::getFreeTid()
165612854Sgabeblack@google.com{
165712854Sgabeblack@google.com    for (ThreadID tid = 0; tid < numThreads; tid++) {
165812854Sgabeblack@google.com        if (!tids[tid]) {
165912854Sgabeblack@google.com            tids[tid] = true;
166012854Sgabeblack@google.com            return tid;
166112854Sgabeblack@google.com        }
166212854Sgabeblack@google.com    }
166312854Sgabeblack@google.com
166412854Sgabeblack@google.com    return InvalidThreadID;
166512854Sgabeblack@google.com}
166612854Sgabeblack@google.com
166712854Sgabeblack@google.comtemplate <class Impl>
166812854Sgabeblack@google.comvoid
166912854Sgabeblack@google.comFullO3CPU<Impl>::updateThreadPriority()
167012854Sgabeblack@google.com{
167112854Sgabeblack@google.com    if (activeThreads.size() > 1) {
167212854Sgabeblack@google.com        //DEFAULT TO ROUND ROBIN SCHEME
167312854Sgabeblack@google.com        //e.g. Move highest priority to end of thread list
167412854Sgabeblack@google.com        list<ThreadID>::iterator list_begin = activeThreads.begin();
167512854Sgabeblack@google.com
167612854Sgabeblack@google.com        unsigned high_thread = *list_begin;
167712854Sgabeblack@google.com
167812854Sgabeblack@google.com        activeThreads.erase(list_begin);
167912854Sgabeblack@google.com
168012854Sgabeblack@google.com        activeThreads.push_back(high_thread);
168112854Sgabeblack@google.com    }
168212854Sgabeblack@google.com}
168312854Sgabeblack@google.com
168412854Sgabeblack@google.com// Forward declaration of FullO3CPU.
168512854Sgabeblack@google.comtemplate class FullO3CPU<O3CPUImpl>;
168612854Sgabeblack@google.com