cpu.cc revision 12284
12623SN/A/*
22623SN/A * Copyright (c) 2011-2012, 2014, 2016, 2017 ARM Limited
32623SN/A * Copyright (c) 2013 Advanced Micro Devices, Inc.
42623SN/A * All rights reserved
52623SN/A *
62623SN/A * The license below extends only to copyright in the software and shall
72623SN/A * not be construed as granting a license to any other intellectual
82623SN/A * property including but not limited to intellectual property relating
92623SN/A * to a hardware implementation of the functionality of the software
102623SN/A * licensed hereunder.  You may use the software subject to the license
112623SN/A * terms below provided that you ensure that this notice is replicated
122623SN/A * unmodified and in its entirety in all distributions of the software,
132623SN/A * modified or unmodified, in source code or in binary form.
142623SN/A *
152623SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan
162623SN/A * Copyright (c) 2011 Regents of the University of California
172623SN/A * All rights reserved.
182623SN/A *
192623SN/A * Redistribution and use in source and binary forms, with or without
202623SN/A * modification, are permitted provided that the following conditions are
212623SN/A * met: redistributions of source code must retain the above copyright
222623SN/A * notice, this list of conditions and the following disclaimer;
232623SN/A * redistributions in binary form must reproduce the above copyright
242623SN/A * notice, this list of conditions and the following disclaimer in the
252623SN/A * documentation and/or other materials provided with the distribution;
262623SN/A * neither the name of the copyright holders nor the names of its
272665Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from
282665Ssaidi@eecs.umich.edu * this software without specific prior written permission.
292623SN/A *
302623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
313170Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
325103Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
332623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
344040Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
356658Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
362623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
372623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
383348Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
393348Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
404762Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
417678Sgblack@eecs.umich.edu *
422901Ssaidi@eecs.umich.edu * Authors: Kevin Lim
432623SN/A *          Korey Sewell
442623SN/A *          Rick Strong
452623SN/A */
462623SN/A
472856Srdreslin@umich.edu#include "cpu/o3/cpu.hh"
482856Srdreslin@umich.edu
492856Srdreslin@umich.edu#include "arch/generic/traits.hh"
502856Srdreslin@umich.edu#include "arch/kernel_stats.hh"
512856Srdreslin@umich.edu#include "config/the_isa.hh"
522856Srdreslin@umich.edu#include "cpu/activity.hh"
532856Srdreslin@umich.edu#include "cpu/checker/cpu.hh"
542856Srdreslin@umich.edu#include "cpu/checker/thread_context.hh"
552856Srdreslin@umich.edu#include "cpu/o3/isa_specific.hh"
562856Srdreslin@umich.edu#include "cpu/o3/thread_context.hh"
572623SN/A#include "cpu/quiesce_event.hh"
582623SN/A#include "cpu/simple_thread.hh"
592623SN/A#include "cpu/thread_context.hh"
602623SN/A#include "debug/Activity.hh"
612623SN/A#include "debug/Drain.hh"
622623SN/A#include "debug/O3CPU.hh"
632680Sktlim@umich.edu#include "debug/Quiesce.hh"
642680Sktlim@umich.edu#include "enums/MemoryMode.hh"
652623SN/A#include "sim/core.hh"
662623SN/A#include "sim/full_system.hh"
675712Shsul@eecs.umich.edu#include "sim/process.hh"
682623SN/A#include "sim/stat_control.hh"
692623SN/A#include "sim/system.hh"
702623SN/A
712623SN/A#if THE_ISA == ALPHA_ISA
722623SN/A#include "arch/alpha/osfpal.hh"
733349Sbinkertn@umich.edu#include "debug/Activity.hh"
742623SN/A
752623SN/A#endif
762623SN/A
772623SN/Astruct BaseCPUParams;
782623SN/A
792623SN/Ausing namespace TheISA;
803349Sbinkertn@umich.eduusing namespace std;
812623SN/A
823184Srdreslin@umich.eduBaseO3CPU::BaseO3CPU(BaseCPUParams *params)
833184Srdreslin@umich.edu    : BaseCPU(params)
842623SN/A{
852623SN/A}
862623SN/A
872623SN/Avoid
882623SN/ABaseO3CPU::regStats()
893647Srdreslin@umich.edu{
903647Srdreslin@umich.edu    BaseCPU::regStats();
913647Srdreslin@umich.edu}
923647Srdreslin@umich.edu
933647Srdreslin@umich.edutemplate<class Impl>
942631SN/Abool
953647Srdreslin@umich.eduFullO3CPU<Impl>::IcachePort::recvTimingResp(PacketPtr pkt)
962631SN/A{
972623SN/A    DPRINTF(O3CPU, "Fetch unit received timing\n");
982623SN/A    // We shouldn't ever get a cacheable block in Modified state
992623SN/A    assert(pkt->req->isUncacheable() ||
1002948Ssaidi@eecs.umich.edu           !(pkt->cacheResponding() && !pkt->hasSharers()));
1012948Ssaidi@eecs.umich.edu    fetch->processCacheCompletion(pkt);
1023349Sbinkertn@umich.edu
1032948Ssaidi@eecs.umich.edu    return true;
1042948Ssaidi@eecs.umich.edu}
1055606Snate@binkert.org
1062948Ssaidi@eecs.umich.edutemplate<class Impl>
1072948Ssaidi@eecs.umich.eduvoid
1085529Snate@binkert.orgFullO3CPU<Impl>::IcachePort::recvReqRetry()
1095894Sgblack@eecs.umich.edu{
1105894Sgblack@eecs.umich.edu    fetch->recvReqRetry();
1112623SN/A}
1122623SN/A
1133647Srdreslin@umich.edutemplate <class Impl>
1143647Srdreslin@umich.edubool
1153647Srdreslin@umich.eduFullO3CPU<Impl>::DcachePort::recvTimingResp(PacketPtr pkt)
1163647Srdreslin@umich.edu{
1172623SN/A    return lsq->recvTimingResp(pkt);
1182839Sktlim@umich.edu}
1193222Sktlim@umich.edu
1202901Ssaidi@eecs.umich.edutemplate <class Impl>
1212623SN/Avoid
1222623SN/AFullO3CPU<Impl>::DcachePort::recvTimingSnoopReq(PacketPtr pkt)
1232623SN/A{
1242623SN/A    for (ThreadID tid = 0; tid < cpu->numThreads; tid++) {
1252623SN/A        if (cpu->getCpuAddrMonitor(tid)->doMonitor(pkt)) {
1262623SN/A            cpu->wakeup(tid);
1272623SN/A        }
1282623SN/A    }
1292623SN/A    lsq->recvTimingSnoopReq(pkt);
1302623SN/A}
1312915Sktlim@umich.edu
1322915Sktlim@umich.edutemplate <class Impl>
1332623SN/Avoid
1342623SN/AFullO3CPU<Impl>::DcachePort::recvReqRetry()
1352623SN/A{
1362623SN/A    lsq->recvReqRetry();
1372623SN/A}
1382623SN/A
1392915Sktlim@umich.edutemplate <class Impl>
1402915Sktlim@umich.eduFullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
1412623SN/A    : BaseO3CPU(params),
1422798Sktlim@umich.edu      itb(params->itb),
1432798Sktlim@umich.edu      dtb(params->dtb),
1442901Ssaidi@eecs.umich.edu      tickEvent([this]{ tick(); }, "FullO3CPU tick",
1452839Sktlim@umich.edu                false, Event::CPU_Tick_Pri),
1462798Sktlim@umich.edu#ifndef NDEBUG
1472839Sktlim@umich.edu      instcount(0),
1482798Sktlim@umich.edu#endif
1495496Ssaidi@eecs.umich.edu      removeInstsThisCycle(false),
1502901Ssaidi@eecs.umich.edu      fetch(this, params),
1512901Ssaidi@eecs.umich.edu      decode(this, params),
1522798Sktlim@umich.edu      rename(this, params),
1532839Sktlim@umich.edu      iew(this, params),
1542839Sktlim@umich.edu      commit(this, params),
1552901Ssaidi@eecs.umich.edu
1562798Sktlim@umich.edu      /* It is mandatory that all SMT threads use the same renaming mode as
1572623SN/A       * they are sharing registers and rename */
1582623SN/A      vecMode(initRenameMode<TheISA::ISA>::mode(params->isa[0])),
1592623SN/A      regFile(params->numPhysIntRegs,
1602798Sktlim@umich.edu              params->numPhysFloatRegs,
1612623SN/A              params->numPhysVecRegs,
1625221Ssaidi@eecs.umich.edu              params->numPhysCCRegs,
1632798Sktlim@umich.edu              vecMode),
1644762Snate@binkert.org
1653201Shsul@eecs.umich.edu      freeList(name() + ".freelist", &regFile),
1665710Scws3k@cs.virginia.edu
1675710Scws3k@cs.virginia.edu      rob(this, params),
1682915Sktlim@umich.edu
1695710Scws3k@cs.virginia.edu      scoreboard(name() + ".scoreboard",
1702623SN/A                 regFile.totalNumPhysRegs()),
1712798Sktlim@umich.edu
1722901Ssaidi@eecs.umich.edu      isa(numThreads, NULL),
1732798Sktlim@umich.edu
1742798Sktlim@umich.edu      icachePort(&fetch, this),
1752798Sktlim@umich.edu      dcachePort(&iew.ldstQueue, this),
1762798Sktlim@umich.edu
1772798Sktlim@umich.edu      timeBuffer(params->backComSize, params->forwardComSize),
1785496Ssaidi@eecs.umich.edu      fetchQueue(params->backComSize, params->forwardComSize),
1792798Sktlim@umich.edu      decodeQueue(params->backComSize, params->forwardComSize),
1805099Ssaidi@eecs.umich.edu      renameQueue(params->backComSize, params->forwardComSize),
1812867Sktlim@umich.edu      iewQueue(params->backComSize, params->forwardComSize),
1822867Sktlim@umich.edu      activityRec(name(), NumStages,
1832867Sktlim@umich.edu                  params->backComSize + params->forwardComSize,
1845710Scws3k@cs.virginia.edu                  params->activity),
1855606Snate@binkert.org
1862623SN/A      globalSeqNum(1),
1872623SN/A      system(params->system),
1882623SN/A      lastRunningCycle(curCycle())
1892623SN/A{
1902623SN/A    if (!params->switched_out) {
1912623SN/A        _status = Running;
1924192Sktlim@umich.edu    } else {
1932623SN/A        _status = SwitchedOut;
1942680Sktlim@umich.edu    }
1952623SN/A
1962680Sktlim@umich.edu    if (params->checker) {
1972680Sktlim@umich.edu        BaseCPU *temp_checker = params->checker;
1982680Sktlim@umich.edu        checker = dynamic_cast<Checker<Impl> *>(temp_checker);
1992623SN/A        checker->setIcachePort(&icachePort);
2002623SN/A        checker->setSystem(params->system);
2012623SN/A    } else {
2022623SN/A        checker = NULL;
2033201Shsul@eecs.umich.edu    }
2043201Shsul@eecs.umich.edu
2053201Shsul@eecs.umich.edu    if (!FullSystem) {
2063201Shsul@eecs.umich.edu        thread.resize(numThreads);
2075169Ssaidi@eecs.umich.edu        tids.resize(numThreads);
2085101Ssaidi@eecs.umich.edu    }
2092623SN/A
2102623SN/A    // The stages also need their CPU pointer setup.  However this
2112623SN/A    // must be done at the upper level CPU because they have pointers
2122623SN/A    // to the upper level CPU, and not this FullO3CPU.
2132623SN/A
2142623SN/A    // Set up Pointers to the activeThreads list for each stage
2155221Ssaidi@eecs.umich.edu    fetch.setActiveThreads(&activeThreads);
2165221Ssaidi@eecs.umich.edu    decode.setActiveThreads(&activeThreads);
2172623SN/A    rename.setActiveThreads(&activeThreads);
2182683Sktlim@umich.edu    iew.setActiveThreads(&activeThreads);
2192623SN/A    commit.setActiveThreads(&activeThreads);
2202623SN/A
2212623SN/A    // Give each of the stages the time buffer they will use.
2222623SN/A    fetch.setTimeBuffer(&timeBuffer);
2232623SN/A    decode.setTimeBuffer(&timeBuffer);
2243686Sktlim@umich.edu    rename.setTimeBuffer(&timeBuffer);
2252623SN/A    iew.setTimeBuffer(&timeBuffer);
2265606Snate@binkert.org    commit.setTimeBuffer(&timeBuffer);
2272623SN/A
2282623SN/A    // Also setup each of the stages' queues.
2292623SN/A    fetch.setFetchQueue(&fetchQueue);
2302623SN/A    decode.setFetchQueue(&fetchQueue);
2312623SN/A    commit.setFetchQueue(&fetchQueue);
2322623SN/A    decode.setDecodeQueue(&decodeQueue);
2335221Ssaidi@eecs.umich.edu    rename.setDecodeQueue(&decodeQueue);
2345221Ssaidi@eecs.umich.edu    rename.setRenameQueue(&renameQueue);
2352623SN/A    iew.setRenameQueue(&renameQueue);
2362683Sktlim@umich.edu    iew.setIEWQueue(&iewQueue);
2372623SN/A    commit.setIEWQueue(&iewQueue);
2386043Sgblack@eecs.umich.edu    commit.setRenameQueue(&renameQueue);
2396043Sgblack@eecs.umich.edu
2406043Sgblack@eecs.umich.edu    commit.setIEWStage(&iew);
2412644Sstever@eecs.umich.edu    rename.setIEWStage(&iew);
2422623SN/A    rename.setCommitStage(&commit);
2432644Sstever@eecs.umich.edu
2442644Sstever@eecs.umich.edu    ThreadID active_threads;
2452623SN/A    if (FullSystem) {
2462623SN/A        active_threads = 1;
2472623SN/A    } else {
2482623SN/A        active_threads = params->workload.size();
2492623SN/A
2505728Sgblack@eecs.umich.edu        if (active_threads > Impl::MaxThreads) {
2515728Sgblack@eecs.umich.edu            panic("Workload Size too large. Increase the 'MaxThreads' "
2525728Sgblack@eecs.umich.edu                  "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) "
2535728Sgblack@eecs.umich.edu                  "or edit your workload size.");
2545728Sgblack@eecs.umich.edu        }
2555728Sgblack@eecs.umich.edu    }
2565728Sgblack@eecs.umich.edu
2575728Sgblack@eecs.umich.edu    //Make Sure That this a Valid Architeture
2585728Sgblack@eecs.umich.edu    assert(params->numPhysIntRegs   >= numThreads * TheISA::NumIntRegs);
2595728Sgblack@eecs.umich.edu    assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
2605728Sgblack@eecs.umich.edu    assert(params->numPhysVecRegs >= numThreads * TheISA::NumVecRegs);
2615728Sgblack@eecs.umich.edu    assert(params->numPhysCCRegs >= numThreads * TheISA::NumCCRegs);
2625728Sgblack@eecs.umich.edu
2635728Sgblack@eecs.umich.edu    rename.setScoreboard(&scoreboard);
2645728Sgblack@eecs.umich.edu    iew.setScoreboard(&scoreboard);
2655728Sgblack@eecs.umich.edu
2665728Sgblack@eecs.umich.edu    // Setup the rename map for whichever stages need it.
2675728Sgblack@eecs.umich.edu    for (ThreadID tid = 0; tid < numThreads; tid++) {
2685728Sgblack@eecs.umich.edu        isa[tid] = params->isa[tid];
2695728Sgblack@eecs.umich.edu        assert(initRenameMode<TheISA::ISA>::equals(isa[tid], isa[0]));
2702623SN/A
2715894Sgblack@eecs.umich.edu        // Only Alpha has an FP zero register, so for other ISAs we
2726973Stjones1@inf.ed.ac.uk        // use an invalid FP register index to avoid special treatment
2736973Stjones1@inf.ed.ac.uk        // of any valid FP reg.
2745744Sgblack@eecs.umich.edu        RegIndex invalidFPReg = TheISA::NumFloatRegs + 1;
2755894Sgblack@eecs.umich.edu        RegIndex fpZeroReg =
2765894Sgblack@eecs.umich.edu            (THE_ISA == ALPHA_ISA) ? TheISA::ZeroReg : invalidFPReg;
2777691SAli.Saidi@ARM.com
2785894Sgblack@eecs.umich.edu        commitRenameMap[tid].init(&regFile, TheISA::ZeroReg, fpZeroReg,
2795894Sgblack@eecs.umich.edu                                  &freeList,
2805894Sgblack@eecs.umich.edu                                  vecMode);
2815894Sgblack@eecs.umich.edu
2825894Sgblack@eecs.umich.edu        renameMap[tid].init(&regFile, TheISA::ZeroReg, fpZeroReg,
2835894Sgblack@eecs.umich.edu                            &freeList, vecMode);
2845894Sgblack@eecs.umich.edu    }
2855894Sgblack@eecs.umich.edu
2865894Sgblack@eecs.umich.edu    // Initialize rename map to assign physical registers to the
2876102Sgblack@eecs.umich.edu    // architectural registers for active threads only.
2885894Sgblack@eecs.umich.edu    for (ThreadID tid = 0; tid < active_threads; tid++) {
2895894Sgblack@eecs.umich.edu        for (RegIndex ridx = 0; ridx < TheISA::NumIntRegs; ++ridx) {
2905894Sgblack@eecs.umich.edu            // Note that we can't use the rename() method because we don't
2915894Sgblack@eecs.umich.edu            // want special treatment for the zero register at this point
2925894Sgblack@eecs.umich.edu            PhysRegIdPtr phys_reg = freeList.getIntReg();
2935894Sgblack@eecs.umich.edu            renameMap[tid].setEntry(RegId(IntRegClass, ridx), phys_reg);
2945894Sgblack@eecs.umich.edu            commitRenameMap[tid].setEntry(RegId(IntRegClass, ridx), phys_reg);
2955894Sgblack@eecs.umich.edu        }
2965894Sgblack@eecs.umich.edu
2975894Sgblack@eecs.umich.edu        for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) {
2985894Sgblack@eecs.umich.edu            PhysRegIdPtr phys_reg = freeList.getFloatReg();
2995894Sgblack@eecs.umich.edu            renameMap[tid].setEntry(RegId(FloatRegClass, ridx), phys_reg);
3005894Sgblack@eecs.umich.edu            commitRenameMap[tid].setEntry(
3015894Sgblack@eecs.umich.edu                    RegId(FloatRegClass, ridx), phys_reg);
3025894Sgblack@eecs.umich.edu        }
3035894Sgblack@eecs.umich.edu
3045894Sgblack@eecs.umich.edu        /* Here we need two 'interfaces' the 'whole register' and the
3056973Stjones1@inf.ed.ac.uk         * 'register element'. At any point only one of them will be
3066973Stjones1@inf.ed.ac.uk         * active. */
3075894Sgblack@eecs.umich.edu        if (vecMode == Enums::Full) {
3085894Sgblack@eecs.umich.edu            /* Initialize the full-vector interface */
3095894Sgblack@eecs.umich.edu            for (RegIndex ridx = 0; ridx < TheISA::NumVecRegs; ++ridx) {
3105894Sgblack@eecs.umich.edu                RegId rid = RegId(VecRegClass, ridx);
3115894Sgblack@eecs.umich.edu                PhysRegIdPtr phys_reg = freeList.getVecReg();
3125894Sgblack@eecs.umich.edu                renameMap[tid].setEntry(rid, phys_reg);
3135894Sgblack@eecs.umich.edu                commitRenameMap[tid].setEntry(rid, phys_reg);
3145894Sgblack@eecs.umich.edu            }
3155894Sgblack@eecs.umich.edu        } else {
3165894Sgblack@eecs.umich.edu            /* Initialize the vector-element interface */
3175894Sgblack@eecs.umich.edu            for (RegIndex ridx = 0; ridx < TheISA::NumVecRegs; ++ridx) {
3185894Sgblack@eecs.umich.edu                for (ElemIndex ldx = 0; ldx < TheISA::NumVecElemPerVecReg;
3195894Sgblack@eecs.umich.edu                        ++ldx) {
3205894Sgblack@eecs.umich.edu                    RegId lrid = RegId(VecElemClass, ridx, ldx);
3215894Sgblack@eecs.umich.edu                    PhysRegIdPtr phys_elem = freeList.getVecElem();
3225894Sgblack@eecs.umich.edu                    renameMap[tid].setEntry(lrid, phys_elem);
3235894Sgblack@eecs.umich.edu                    commitRenameMap[tid].setEntry(lrid, phys_elem);
3245894Sgblack@eecs.umich.edu                }
3255894Sgblack@eecs.umich.edu            }
3265894Sgblack@eecs.umich.edu        }
3275894Sgblack@eecs.umich.edu
3285894Sgblack@eecs.umich.edu        for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) {
3295894Sgblack@eecs.umich.edu            PhysRegIdPtr phys_reg = freeList.getCCReg();
3305894Sgblack@eecs.umich.edu            renameMap[tid].setEntry(RegId(CCRegClass, ridx), phys_reg);
3315894Sgblack@eecs.umich.edu            commitRenameMap[tid].setEntry(RegId(CCRegClass, ridx), phys_reg);
3325894Sgblack@eecs.umich.edu        }
3335894Sgblack@eecs.umich.edu    }
3345894Sgblack@eecs.umich.edu
3355894Sgblack@eecs.umich.edu    rename.setRenameMap(renameMap);
3365894Sgblack@eecs.umich.edu    commit.setRenameMap(commitRenameMap);
3375894Sgblack@eecs.umich.edu    rename.setFreeList(&freeList);
3385894Sgblack@eecs.umich.edu
3395894Sgblack@eecs.umich.edu    // Setup the ROB for whichever stages need it.
3405894Sgblack@eecs.umich.edu    commit.setROB(&rob);
3415894Sgblack@eecs.umich.edu
3425894Sgblack@eecs.umich.edu    lastActivatedCycle = 0;
3435894Sgblack@eecs.umich.edu#if 0
3446739Sgblack@eecs.umich.edu    // Give renameMap & rename stage access to the freeList;
3456739Sgblack@eecs.umich.edu    for (ThreadID tid = 0; tid < numThreads; tid++)
3465894Sgblack@eecs.umich.edu        globalSeqNum[tid] = 1;
3475894Sgblack@eecs.umich.edu#endif
3485894Sgblack@eecs.umich.edu
3495894Sgblack@eecs.umich.edu    DPRINTF(O3CPU, "Creating O3CPU object.\n");
3505894Sgblack@eecs.umich.edu
3515894Sgblack@eecs.umich.edu    // Setup any thread state.
3525894Sgblack@eecs.umich.edu    this->thread.resize(this->numThreads);
3535744Sgblack@eecs.umich.edu
3545744Sgblack@eecs.umich.edu    for (ThreadID tid = 0; tid < this->numThreads; ++tid) {
3555894Sgblack@eecs.umich.edu        if (FullSystem) {
3565894Sgblack@eecs.umich.edu            // SMT is not supported in FS mode yet.
3575894Sgblack@eecs.umich.edu            assert(this->numThreads == 1);
3585894Sgblack@eecs.umich.edu            this->thread[tid] = new Thread(this, 0, NULL);
3595894Sgblack@eecs.umich.edu        } else {
3605894Sgblack@eecs.umich.edu            if (tid < params->workload.size()) {
3615894Sgblack@eecs.umich.edu                DPRINTF(O3CPU, "Workload[%i] process is %#x",
3625894Sgblack@eecs.umich.edu                        tid, this->thread[tid]);
3635894Sgblack@eecs.umich.edu                this->thread[tid] = new typename FullO3CPU<Impl>::Thread(
3645894Sgblack@eecs.umich.edu                        (typename Impl::O3CPU *)(this),
3655894Sgblack@eecs.umich.edu                        tid, params->workload[tid]);
3665894Sgblack@eecs.umich.edu
3675894Sgblack@eecs.umich.edu                //usedTids[tid] = true;
3685894Sgblack@eecs.umich.edu                //threadMap[tid] = tid;
3695894Sgblack@eecs.umich.edu            } else {
3705894Sgblack@eecs.umich.edu                //Allocate Empty thread so M5 can use later
3716102Sgblack@eecs.umich.edu                //when scheduling threads to CPU
3725894Sgblack@eecs.umich.edu                Process* dummy_proc = NULL;
3735894Sgblack@eecs.umich.edu
3745894Sgblack@eecs.umich.edu                this->thread[tid] = new typename FullO3CPU<Impl>::Thread(
3756102Sgblack@eecs.umich.edu                        (typename Impl::O3CPU *)(this),
3765894Sgblack@eecs.umich.edu                        tid, dummy_proc);
3775894Sgblack@eecs.umich.edu                //usedTids[tid] = false;
3785894Sgblack@eecs.umich.edu            }
3795894Sgblack@eecs.umich.edu        }
3805894Sgblack@eecs.umich.edu
3815894Sgblack@eecs.umich.edu        ThreadContext *tc;
3825894Sgblack@eecs.umich.edu
3835894Sgblack@eecs.umich.edu        // Setup the TC that will serve as the interface to the threads/CPU.
3845894Sgblack@eecs.umich.edu        O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>;
3855894Sgblack@eecs.umich.edu
3865894Sgblack@eecs.umich.edu        tc = o3_tc;
3875894Sgblack@eecs.umich.edu
3885894Sgblack@eecs.umich.edu        // If we're using a checker, then the TC should be the
3895894Sgblack@eecs.umich.edu        // CheckerThreadContext.
3905894Sgblack@eecs.umich.edu        if (params->checker) {
3915744Sgblack@eecs.umich.edu            tc = new CheckerThreadContext<O3ThreadContext<Impl> >(
3925744Sgblack@eecs.umich.edu                o3_tc, this->checker);
3935894Sgblack@eecs.umich.edu        }
3945894Sgblack@eecs.umich.edu
3955894Sgblack@eecs.umich.edu        o3_tc->cpu = (typename Impl::O3CPU *)(this);
3965894Sgblack@eecs.umich.edu        assert(o3_tc->cpu);
3975894Sgblack@eecs.umich.edu        o3_tc->thread = this->thread[tid];
3985894Sgblack@eecs.umich.edu
3995894Sgblack@eecs.umich.edu        // Setup quiesce event.
4005894Sgblack@eecs.umich.edu        this->thread[tid]->quiesceEvent = new EndQuiesceEvent(tc);
4015744Sgblack@eecs.umich.edu
4025744Sgblack@eecs.umich.edu        // Give the thread the TC.
4035744Sgblack@eecs.umich.edu        this->thread[tid]->tc = tc;
4045744Sgblack@eecs.umich.edu
4057691SAli.Saidi@ARM.com        // Add the TC to the CPU's list of TC's.
4065744Sgblack@eecs.umich.edu        this->threadContexts.push_back(tc);
4075744Sgblack@eecs.umich.edu    }
4085744Sgblack@eecs.umich.edu
4095744Sgblack@eecs.umich.edu    // FullO3CPU always requires an interrupt controller.
4105744Sgblack@eecs.umich.edu    if (!params->switched_out && interrupts.empty()) {
4115744Sgblack@eecs.umich.edu        fatal("FullO3CPU %s has no interrupt controller.\n"
4125744Sgblack@eecs.umich.edu              "Ensure createInterruptController() is called.\n", name());
4135744Sgblack@eecs.umich.edu    }
4145744Sgblack@eecs.umich.edu
4155744Sgblack@eecs.umich.edu    for (ThreadID tid = 0; tid < this->numThreads; tid++)
4165744Sgblack@eecs.umich.edu        this->thread[tid]->setFuncExeInst(0);
4175744Sgblack@eecs.umich.edu}
4182623SN/A
4197520Sgblack@eecs.umich.edutemplate <class Impl>
4207520Sgblack@eecs.umich.eduFullO3CPU<Impl>::~FullO3CPU()
4212623SN/A{
4225728Sgblack@eecs.umich.edu}
4235728Sgblack@eecs.umich.edu
4246221Snate@binkert.orgtemplate <class Impl>
4257720Sgblack@eecs.umich.eduvoid
4266227Snate@binkert.orgFullO3CPU<Impl>::regProbePoints()
4276973Stjones1@inf.ed.ac.uk{
4282623SN/A    BaseCPU::regProbePoints();
4297045Ssteve.reinhardt@amd.com
4307045Ssteve.reinhardt@amd.com    ppInstAccessComplete = new ProbePointArg<PacketPtr>(getProbeManager(), "InstAccessComplete");
4317045Ssteve.reinhardt@amd.com    ppDataAccessComplete = new ProbePointArg<std::pair<DynInstPtr, PacketPtr> >(getProbeManager(), "DataAccessComplete");
4327045Ssteve.reinhardt@amd.com
4337520Sgblack@eecs.umich.edu    fetch.regProbePoints();
4346221Snate@binkert.org    rename.regProbePoints();
4355728Sgblack@eecs.umich.edu    iew.regProbePoints();
4367520Sgblack@eecs.umich.edu    commit.regProbePoints();
4375744Sgblack@eecs.umich.edu}
4385728Sgblack@eecs.umich.edu
4395894Sgblack@eecs.umich.edutemplate <class Impl>
4405744Sgblack@eecs.umich.eduvoid
4415894Sgblack@eecs.umich.eduFullO3CPU<Impl>::regStats()
4426102Sgblack@eecs.umich.edu{
4435894Sgblack@eecs.umich.edu    BaseO3CPU::regStats();
4445894Sgblack@eecs.umich.edu
4456973Stjones1@inf.ed.ac.uk    // Register any of the O3CPU's stats here.
4467520Sgblack@eecs.umich.edu    timesIdled
4476973Stjones1@inf.ed.ac.uk        .name(name() + ".timesIdled")
4486973Stjones1@inf.ed.ac.uk        .desc("Number of times that the entire CPU went into an idle state and"
4496973Stjones1@inf.ed.ac.uk              " unscheduled itself")
4506973Stjones1@inf.ed.ac.uk        .prereq(timesIdled);
4516973Stjones1@inf.ed.ac.uk
4526973Stjones1@inf.ed.ac.uk    idleCycles
4536973Stjones1@inf.ed.ac.uk        .name(name() + ".idleCycles")
4546973Stjones1@inf.ed.ac.uk        .desc("Total number of cycles that the CPU has spent unscheduled due "
4555744Sgblack@eecs.umich.edu              "to idling")
4566973Stjones1@inf.ed.ac.uk        .prereq(idleCycles);
4577520Sgblack@eecs.umich.edu
4586973Stjones1@inf.ed.ac.uk    quiesceCycles
4596973Stjones1@inf.ed.ac.uk        .name(name() + ".quiesceCycles")
4606973Stjones1@inf.ed.ac.uk        .desc("Total number of cycles that CPU has spent quiesced or waiting "
4612623SN/A              "for an interrupt")
4622623SN/A        .prereq(quiesceCycles);
4635728Sgblack@eecs.umich.edu
4642623SN/A    // Number of Instructions simulated
4652623SN/A    // --------------------------------
4667520Sgblack@eecs.umich.edu    // Should probably be in Base CPU but need templated
4677520Sgblack@eecs.umich.edu    // MaxThreads so put in here instead
4687520Sgblack@eecs.umich.edu    committedInsts
4697520Sgblack@eecs.umich.edu        .init(numThreads)
4707520Sgblack@eecs.umich.edu        .name(name() + ".committedInsts")
4717520Sgblack@eecs.umich.edu        .desc("Number of Instructions Simulated")
4727520Sgblack@eecs.umich.edu        .flags(Stats::total);
4732623SN/A
4742623SN/A    committedOps
4752623SN/A        .init(numThreads)
4762623SN/A        .name(name() + ".committedOps")
4774040Ssaidi@eecs.umich.edu        .desc("Number of Ops (including micro ops) Simulated")
4784040Ssaidi@eecs.umich.edu        .flags(Stats::total);
4794040Ssaidi@eecs.umich.edu
4804040Ssaidi@eecs.umich.edu    cpi
4814115Ssaidi@eecs.umich.edu        .name(name() + ".cpi")
4824115Ssaidi@eecs.umich.edu        .desc("CPI: Cycles Per Instruction")
4834115Ssaidi@eecs.umich.edu        .precision(6);
4844115Ssaidi@eecs.umich.edu    cpi = numCycles / committedInsts;
4852623SN/A
4862623SN/A    totalCpi
4872623SN/A        .name(name() + ".cpi_total")
4882623SN/A        .desc("CPI: Total CPI of All Threads")
4892623SN/A        .precision(6);
4902623SN/A    totalCpi = numCycles / sum(committedInsts);
4912623SN/A
4922623SN/A    ipc
4932623SN/A        .name(name() + ".ipc")
4942623SN/A        .desc("IPC: Instructions Per Cycle")
4952623SN/A        .precision(6);
4962623SN/A    ipc =  committedInsts / numCycles;
4972623SN/A
4982623SN/A    totalIpc
4992623SN/A        .name(name() + ".ipc_total")
5002623SN/A        .desc("IPC: Total IPC of All Threads")
5012623SN/A        .precision(6);
5022623SN/A    totalIpc =  sum(committedInsts) / numCycles;
5032623SN/A
5042623SN/A    this->fetch.regStats();
5052623SN/A    this->decode.regStats();
5062623SN/A    this->rename.regStats();
5072623SN/A    this->iew.regStats();
5082623SN/A    this->commit.regStats();
5092623SN/A    this->rob.regStats();
5102623SN/A
5112623SN/A    intRegfileReads
5122623SN/A        .name(name() + ".int_regfile_reads")
5132623SN/A        .desc("number of integer regfile reads")
5142623SN/A        .prereq(intRegfileReads);
5152623SN/A
5162623SN/A    intRegfileWrites
5172623SN/A        .name(name() + ".int_regfile_writes")
5182623SN/A        .desc("number of integer regfile writes")
5192623SN/A        .prereq(intRegfileWrites);
5202623SN/A
5212623SN/A    fpRegfileReads
5225728Sgblack@eecs.umich.edu        .name(name() + ".fp_regfile_reads")
5235728Sgblack@eecs.umich.edu        .desc("number of floating regfile reads")
5245728Sgblack@eecs.umich.edu        .prereq(fpRegfileReads);
5255728Sgblack@eecs.umich.edu
5265728Sgblack@eecs.umich.edu    fpRegfileWrites
5275728Sgblack@eecs.umich.edu        .name(name() + ".fp_regfile_writes")
5285728Sgblack@eecs.umich.edu        .desc("number of floating regfile writes")
5295728Sgblack@eecs.umich.edu        .prereq(fpRegfileWrites);
5305728Sgblack@eecs.umich.edu
5315728Sgblack@eecs.umich.edu    vecRegfileReads
5325728Sgblack@eecs.umich.edu        .name(name() + ".vec_regfile_reads")
5335728Sgblack@eecs.umich.edu        .desc("number of vector regfile reads")
5345728Sgblack@eecs.umich.edu        .prereq(vecRegfileReads);
5355728Sgblack@eecs.umich.edu
5365728Sgblack@eecs.umich.edu    vecRegfileWrites
5375728Sgblack@eecs.umich.edu        .name(name() + ".vec_regfile_writes")
5385728Sgblack@eecs.umich.edu        .desc("number of vector regfile writes")
5395728Sgblack@eecs.umich.edu        .prereq(vecRegfileWrites);
5405728Sgblack@eecs.umich.edu
5412623SN/A    ccRegfileReads
5422623SN/A        .name(name() + ".cc_regfile_reads")
5437520Sgblack@eecs.umich.edu        .desc("number of cc regfile reads")
5447520Sgblack@eecs.umich.edu        .prereq(ccRegfileReads);
5452623SN/A
5465728Sgblack@eecs.umich.edu    ccRegfileWrites
5476221Snate@binkert.org        .name(name() + ".cc_regfile_writes")
5487720Sgblack@eecs.umich.edu        .desc("number of cc regfile writes")
5496227Snate@binkert.org        .prereq(ccRegfileWrites);
5506973Stjones1@inf.ed.ac.uk
5513169Sstever@eecs.umich.edu    miscRegfileReads
5527045Ssteve.reinhardt@amd.com        .name(name() + ".misc_regfile_reads")
5537045Ssteve.reinhardt@amd.com        .desc("number of misc regfile reads")
5547045Ssteve.reinhardt@amd.com        .prereq(miscRegfileReads);
5557045Ssteve.reinhardt@amd.com
5567520Sgblack@eecs.umich.edu    miscRegfileWrites
5576221Snate@binkert.org        .name(name() + ".misc_regfile_writes")
5585728Sgblack@eecs.umich.edu        .desc("number of misc regfile writes")
5597520Sgblack@eecs.umich.edu        .prereq(miscRegfileWrites);
5605744Sgblack@eecs.umich.edu}
5615728Sgblack@eecs.umich.edu
5625894Sgblack@eecs.umich.edutemplate <class Impl>
5635744Sgblack@eecs.umich.eduvoid
5645894Sgblack@eecs.umich.eduFullO3CPU<Impl>::tick()
5656102Sgblack@eecs.umich.edu{
5665894Sgblack@eecs.umich.edu    DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
5675894Sgblack@eecs.umich.edu    assert(!switchedOut());
5686973Stjones1@inf.ed.ac.uk    assert(drainState() != DrainState::Drained);
5697520Sgblack@eecs.umich.edu
5706973Stjones1@inf.ed.ac.uk    ++numCycles;
5716973Stjones1@inf.ed.ac.uk    updateCycleCounters(BaseCPU::CPU_STATE_ON);
5726973Stjones1@inf.ed.ac.uk
5736973Stjones1@inf.ed.ac.uk//    activity = false;
5746973Stjones1@inf.ed.ac.uk
5756973Stjones1@inf.ed.ac.uk    //Tick each of the stages
5766973Stjones1@inf.ed.ac.uk    fetch.tick();
5775744Sgblack@eecs.umich.edu
5786973Stjones1@inf.ed.ac.uk    decode.tick();
5797520Sgblack@eecs.umich.edu
5806973Stjones1@inf.ed.ac.uk    rename.tick();
5816973Stjones1@inf.ed.ac.uk
5826973Stjones1@inf.ed.ac.uk    iew.tick();
5832623SN/A
5842623SN/A    commit.tick();
5857045Ssteve.reinhardt@amd.com
5865728Sgblack@eecs.umich.edu    // Now advance the time buffers
5872623SN/A    timeBuffer.advance();
5882623SN/A
5897520Sgblack@eecs.umich.edu    fetchQueue.advance();
5907520Sgblack@eecs.umich.edu    decodeQueue.advance();
5917520Sgblack@eecs.umich.edu    renameQueue.advance();
5927520Sgblack@eecs.umich.edu    iewQueue.advance();
5937520Sgblack@eecs.umich.edu
5947520Sgblack@eecs.umich.edu    activityRec.advance();
5957520Sgblack@eecs.umich.edu
5967520Sgblack@eecs.umich.edu    if (removeInstsThisCycle) {
5977520Sgblack@eecs.umich.edu        cleanUpRemovedInsts();
5987520Sgblack@eecs.umich.edu    }
5997520Sgblack@eecs.umich.edu
6007520Sgblack@eecs.umich.edu    if (!tickEvent.scheduled()) {
6017520Sgblack@eecs.umich.edu        if (_status == SwitchedOut) {
6027520Sgblack@eecs.umich.edu            DPRINTF(O3CPU, "Switched out!\n");
6037520Sgblack@eecs.umich.edu            // increment stat
6047520Sgblack@eecs.umich.edu            lastRunningCycle = curCycle();
6057691SAli.Saidi@ARM.com        } else if (!activityRec.active() || _status == Idle) {
6067520Sgblack@eecs.umich.edu            DPRINTF(O3CPU, "Idle!\n");
6077520Sgblack@eecs.umich.edu            lastRunningCycle = curCycle();
6087520Sgblack@eecs.umich.edu            timesIdled++;
6097520Sgblack@eecs.umich.edu        } else {
6107520Sgblack@eecs.umich.edu            schedule(tickEvent, clockEdge(Cycles(1)));
6112623SN/A            DPRINTF(O3CPU, "Scheduling next tick!\n");
6122623SN/A        }
6132623SN/A    }
6142623SN/A
6154224Sgblack@eecs.umich.edu    if (!FullSystem)
6164224Sgblack@eecs.umich.edu        updateThreadPriority();
6174224Sgblack@eecs.umich.edu
6184224Sgblack@eecs.umich.edu    tryDrain();
6194224Sgblack@eecs.umich.edu}
6204224Sgblack@eecs.umich.edu
6214224Sgblack@eecs.umich.edutemplate <class Impl>
6224224Sgblack@eecs.umich.eduvoid
6234224Sgblack@eecs.umich.eduFullO3CPU<Impl>::init()
6244224Sgblack@eecs.umich.edu{
6252623SN/A    BaseCPU::init();
6262623SN/A
6272623SN/A    for (ThreadID tid = 0; tid < numThreads; ++tid) {
6282623SN/A        // Set noSquashFromTC so that the CPU doesn't squash when initially
6292623SN/A        // setting up registers.
6302623SN/A        thread[tid]->noSquashFromTC = true;
6312623SN/A        // Initialise the ThreadContext's memory proxies
6322623SN/A        thread[tid]->initMemProxies(thread[tid]->getTC());
6332623SN/A    }
6342623SN/A
6352623SN/A    if (FullSystem && !params()->switched_out) {
6362623SN/A        for (ThreadID tid = 0; tid < numThreads; tid++) {
6372623SN/A            ThreadContext *src_tc = threadContexts[tid];
6382623SN/A            TheISA::initCPU(src_tc, src_tc->contextId());
6392623SN/A        }
6402623SN/A    }
6412623SN/A
6422623SN/A    // Clear noSquashFromTC.
6432623SN/A    for (int tid = 0; tid < numThreads; ++tid)
6442623SN/A        thread[tid]->noSquashFromTC = false;
6452623SN/A
6462623SN/A    commit.setThreads(thread);
6472623SN/A}
6482623SN/A
6492623SN/Atemplate <class Impl>
6502623SN/Avoid
6512623SN/AFullO3CPU<Impl>::startup()
6522623SN/A{
6532623SN/A    BaseCPU::startup();
6542623SN/A    for (int tid = 0; tid < numThreads; ++tid)
6552623SN/A        isa[tid]->startup(threadContexts[tid]);
6562623SN/A
6572623SN/A    fetch.startupStage();
6582623SN/A    decode.startupStage();
6592623SN/A    iew.startupStage();
6602623SN/A    rename.startupStage();
6612623SN/A    commit.startupStage();
6622623SN/A}
6632623SN/A
6642623SN/Atemplate <class Impl>
6652623SN/Avoid
6662623SN/AFullO3CPU<Impl>::activateThread(ThreadID tid)
6672623SN/A{
6682623SN/A    list<ThreadID>::iterator isActive =
6696973Stjones1@inf.ed.ac.uk        std::find(activeThreads.begin(), activeThreads.end(), tid);
6706973Stjones1@inf.ed.ac.uk
6716973Stjones1@inf.ed.ac.uk    DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid);
6726973Stjones1@inf.ed.ac.uk    assert(!switchedOut());
6736973Stjones1@inf.ed.ac.uk
6746973Stjones1@inf.ed.ac.uk    if (isActive == activeThreads.end()) {
6756973Stjones1@inf.ed.ac.uk        DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n",
6766973Stjones1@inf.ed.ac.uk                tid);
6777691SAli.Saidi@ARM.com
6786973Stjones1@inf.ed.ac.uk        activeThreads.push_back(tid);
6796973Stjones1@inf.ed.ac.uk    }
6806973Stjones1@inf.ed.ac.uk}
6816973Stjones1@inf.ed.ac.uk
6826973Stjones1@inf.ed.ac.uktemplate <class Impl>
6836973Stjones1@inf.ed.ac.ukvoid
6846973Stjones1@inf.ed.ac.ukFullO3CPU<Impl>::deactivateThread(ThreadID tid)
6856973Stjones1@inf.ed.ac.uk{
6866973Stjones1@inf.ed.ac.uk    //Remove From Active List, if Active
6876973Stjones1@inf.ed.ac.uk    list<ThreadID>::iterator thread_it =
6886973Stjones1@inf.ed.ac.uk        std::find(activeThreads.begin(), activeThreads.end(), tid);
6896973Stjones1@inf.ed.ac.uk
6906973Stjones1@inf.ed.ac.uk    DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid);
6916973Stjones1@inf.ed.ac.uk    assert(!switchedOut());
6926973Stjones1@inf.ed.ac.uk
6936973Stjones1@inf.ed.ac.uk    if (thread_it != activeThreads.end()) {
6946973Stjones1@inf.ed.ac.uk        DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
6952623SN/A                tid);
6962623SN/A        activeThreads.erase(thread_it);
6975221Ssaidi@eecs.umich.edu    }
6985221Ssaidi@eecs.umich.edu
6993387Sgblack@eecs.umich.edu    fetch.deactivateThread(tid);
7003387Sgblack@eecs.umich.edu    commit.deactivateThread(tid);
7012631SN/A}
7025348Ssaidi@eecs.umich.edu
7035348Ssaidi@eecs.umich.edutemplate <class Impl>
7047720Sgblack@eecs.umich.eduCounter
7057720Sgblack@eecs.umich.eduFullO3CPU<Impl>::totalInsts() const
7062623SN/A{
7077720Sgblack@eecs.umich.edu    Counter total(0);
7085669Sgblack@eecs.umich.edu
7095712Shsul@eecs.umich.edu    ThreadID size = thread.size();
7105894Sgblack@eecs.umich.edu    for (ThreadID i = 0; i < size; i++)
7116023Snate@binkert.org        total += thread[i]->numInst;
7126023Snate@binkert.org
7132623SN/A    return total;
7145669Sgblack@eecs.umich.edu}
7155669Sgblack@eecs.umich.edu
7165894Sgblack@eecs.umich.edutemplate <class Impl>
7175894Sgblack@eecs.umich.eduCounter
7185894Sgblack@eecs.umich.eduFullO3CPU<Impl>::totalOps() const
7195894Sgblack@eecs.umich.edu{
7205894Sgblack@eecs.umich.edu    Counter total(0);
7215894Sgblack@eecs.umich.edu
7225894Sgblack@eecs.umich.edu    ThreadID size = thread.size();
7235894Sgblack@eecs.umich.edu    for (ThreadID i = 0; i < size; i++)
7245894Sgblack@eecs.umich.edu        total += thread[i]->numOp;
7255894Sgblack@eecs.umich.edu
7265894Sgblack@eecs.umich.edu    return total;
7275894Sgblack@eecs.umich.edu}
7285894Sgblack@eecs.umich.edu
7295894Sgblack@eecs.umich.edutemplate <class Impl>
7305894Sgblack@eecs.umich.eduvoid
7315894Sgblack@eecs.umich.eduFullO3CPU<Impl>::activateContext(ThreadID tid)
7325894Sgblack@eecs.umich.edu{
7335894Sgblack@eecs.umich.edu    assert(!switchedOut());
7345894Sgblack@eecs.umich.edu
7355894Sgblack@eecs.umich.edu    // Needs to set each stage to running as well.
7365894Sgblack@eecs.umich.edu    activateThread(tid);
7375894Sgblack@eecs.umich.edu
7385894Sgblack@eecs.umich.edu    // We don't want to wake the CPU if it is drained. In that case,
7395894Sgblack@eecs.umich.edu    // we just want to flag the thread as active and schedule the tick
7405894Sgblack@eecs.umich.edu    // event from drainResume() instead.
7415894Sgblack@eecs.umich.edu    if (drainState() == DrainState::Drained)
7425894Sgblack@eecs.umich.edu        return;
7432623SN/A
7443222Sktlim@umich.edu    // If we are time 0 or if the last activation time is in the past,
7455099Ssaidi@eecs.umich.edu    // schedule the next tick and wake up the fetch unit
7463222Sktlim@umich.edu    if (lastActivatedCycle == 0 || lastActivatedCycle < curTick()) {
7472623SN/A        scheduleTickEvent(Cycles(0));
7482623SN/A
7492623SN/A        // Be sure to signal that there's some activity so the CPU doesn't
7502623SN/A        // deschedule itself.
7512644Sstever@eecs.umich.edu        activityRec.activity();
7522623SN/A        fetch.wakeFromQuiesce();
7535726Sgblack@eecs.umich.edu
7545726Sgblack@eecs.umich.edu        Cycles cycles(curCycle() - lastRunningCycle);
7552623SN/A        // @todo: This is an oddity that is only here to match the stats
7562631SN/A        if (cycles != 0)
7572631SN/A            --cycles;
7582631SN/A        quiesceCycles += cycles;
7592631SN/A
7602631SN/A        lastActivatedCycle = curTick();
7612631SN/A
7622623SN/A        _status = Running;
7632623SN/A
7642623SN/A        BaseCPU::activateContext(tid);
7652623SN/A    }
7663349Sbinkertn@umich.edu}
7672623SN/A
7685221Ssaidi@eecs.umich.edutemplate <class Impl>
7695221Ssaidi@eecs.umich.eduvoid
7702623SN/AFullO3CPU<Impl>::suspendContext(ThreadID tid)
7712623SN/A{
7725669Sgblack@eecs.umich.edu    DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
7735669Sgblack@eecs.umich.edu    assert(!switchedOut());
7742623SN/A
7752798Sktlim@umich.edu    deactivateThread(tid);
7762623SN/A
7772644Sstever@eecs.umich.edu    // If this was the last thread then unschedule the tick event.
7785099Ssaidi@eecs.umich.edu    if (activeThreads.size() == 0) {
7793222Sktlim@umich.edu        unscheduleTickEvent();
7803222Sktlim@umich.edu        lastRunningCycle = curCycle();
7812839Sktlim@umich.edu        _status = Idle;
7825669Sgblack@eecs.umich.edu    }
7835669Sgblack@eecs.umich.edu
7845669Sgblack@eecs.umich.edu    DPRINTF(Quiesce, "Suspending Context\n");
7855669Sgblack@eecs.umich.edu
7863658Sktlim@umich.edu    BaseCPU::suspendContext(tid);
7872839Sktlim@umich.edu}
7882798Sktlim@umich.edu
7892798Sktlim@umich.edutemplate <class Impl>
7902798Sktlim@umich.eduvoid
7912623SN/AFullO3CPU<Impl>::haltContext(ThreadID tid)
7925726Sgblack@eecs.umich.edu{
7935726Sgblack@eecs.umich.edu    //For now, this is the same as deallocate
7942623SN/A    DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
7952623SN/A    assert(!switchedOut());
7963170Sstever@eecs.umich.edu
7973170Sstever@eecs.umich.edu    deactivateThread(tid);
7985894Sgblack@eecs.umich.edu    removeThread(tid);
7995894Sgblack@eecs.umich.edu
8003170Sstever@eecs.umich.edu    updateCycleCounters(BaseCPU::CPU_STATE_SLEEP);
8012644Sstever@eecs.umich.edu}
8025894Sgblack@eecs.umich.edu
8035001Sgblack@eecs.umich.edutemplate <class Impl>
8045001Sgblack@eecs.umich.eduvoid
8055001Sgblack@eecs.umich.eduFullO3CPU<Impl>::insertThread(ThreadID tid)
8063170Sstever@eecs.umich.edu{
8074998Sgblack@eecs.umich.edu    DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU");
8082644Sstever@eecs.umich.edu    // Will change now that the PC and thread state is internal to the CPU
8095103Ssaidi@eecs.umich.edu    // and not in the ThreadContext.
8105103Ssaidi@eecs.umich.edu    ThreadContext *src_tc;
8115103Ssaidi@eecs.umich.edu    if (FullSystem)
8125103Ssaidi@eecs.umich.edu        src_tc = system->threadContexts[tid];
8132644Sstever@eecs.umich.edu    else
8142644Sstever@eecs.umich.edu        src_tc = tcBase(tid);
8155726Sgblack@eecs.umich.edu
8162623SN/A    //Bind Int Regs to Rename Map
8172623SN/A
8184998Sgblack@eecs.umich.edu    for (RegId reg_id(IntRegClass, 0); reg_id.index() < TheISA::NumIntRegs;
8194998Sgblack@eecs.umich.edu         reg_id.index()++) {
8204998Sgblack@eecs.umich.edu        PhysRegIdPtr phys_reg = freeList.getIntReg();
8214998Sgblack@eecs.umich.edu        renameMap[tid].setEntry(reg_id, phys_reg);
8227655Sali.saidi@arm.com        scoreboard.setReg(phys_reg);
8235001Sgblack@eecs.umich.edu    }
8245001Sgblack@eecs.umich.edu
8255001Sgblack@eecs.umich.edu    //Bind Float Regs to Rename Map
8264998Sgblack@eecs.umich.edu    for (RegId reg_id(FloatRegClass, 0); reg_id.index() < TheISA::NumFloatRegs;
8272644Sstever@eecs.umich.edu         reg_id.index()++) {
8285103Ssaidi@eecs.umich.edu        PhysRegIdPtr phys_reg = freeList.getFloatReg();
8295103Ssaidi@eecs.umich.edu        renameMap[tid].setEntry(reg_id, phys_reg);
8305103Ssaidi@eecs.umich.edu        scoreboard.setReg(phys_reg);
8315103Ssaidi@eecs.umich.edu    }
8322644Sstever@eecs.umich.edu
8335726Sgblack@eecs.umich.edu    //Bind condition-code Regs to Rename Map
8345726Sgblack@eecs.umich.edu    for (RegId reg_id(CCRegClass, 0); reg_id.index() < TheISA::NumCCRegs;
8352623SN/A         reg_id.index()++) {
8363658Sktlim@umich.edu        PhysRegIdPtr phys_reg = freeList.getCCReg();
8375669Sgblack@eecs.umich.edu        renameMap[tid].setEntry(reg_id, phys_reg);
8385669Sgblack@eecs.umich.edu        scoreboard.setReg(phys_reg);
8395669Sgblack@eecs.umich.edu    }
8405669Sgblack@eecs.umich.edu
8412623SN/A    //Copy Thread Data Into RegFile
8422623SN/A    //this->copyFromTC(tid);
8432948Ssaidi@eecs.umich.edu
8442948Ssaidi@eecs.umich.edu    //Set PC/NPC/NNPC
8452948Ssaidi@eecs.umich.edu    pcState(src_tc->pcState(), tid);
8462948Ssaidi@eecs.umich.edu
8472948Ssaidi@eecs.umich.edu    src_tc->setStatus(ThreadContext::Active);
8482623SN/A
8492623SN/A    activateContext(tid);
8503349Sbinkertn@umich.edu
8512623SN/A    //Reset ROB/IQ/LSQ Entries
8524986Ssaidi@eecs.umich.edu    commit.rob->resetEntries();
8533310Srdreslin@umich.edu    iew.resetEntries();
8544584Ssaidi@eecs.umich.edu}
8552948Ssaidi@eecs.umich.edu
8563495Sktlim@umich.edutemplate <class Impl>
8573310Srdreslin@umich.eduvoid
8583310Srdreslin@umich.eduFullO3CPU<Impl>::removeThread(ThreadID tid)
8593495Sktlim@umich.edu{
8602948Ssaidi@eecs.umich.edu    DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid);
8613310Srdreslin@umich.edu
8623310Srdreslin@umich.edu    // Copy Thread Data From RegFile
8634870Sstever@eecs.umich.edu    // If thread is suspended, it might be re-allocated
8644433Ssaidi@eecs.umich.edu    // this->copyToTC(tid);
8654433Ssaidi@eecs.umich.edu
8664433Ssaidi@eecs.umich.edu
8674433Ssaidi@eecs.umich.edu    // @todo: 2-27-2008: Fix how we free up rename mappings
8684433Ssaidi@eecs.umich.edu    // here to alleviate the case for double-freeing registers
8694433Ssaidi@eecs.umich.edu    // in SMT workloads.
8703310Srdreslin@umich.edu
8714433Ssaidi@eecs.umich.edu    // Unbind Int Regs from Rename Map
8724433Ssaidi@eecs.umich.edu    for (RegId reg_id(IntRegClass, 0); reg_id.index() < TheISA::NumIntRegs;
8732623SN/A         reg_id.index()++) {
8742623SN/A        PhysRegIdPtr phys_reg = renameMap[tid].lookup(reg_id);
8752657Ssaidi@eecs.umich.edu        scoreboard.unsetReg(phys_reg);
8762623SN/A        freeList.addReg(phys_reg);
8772623SN/A    }
8782623SN/A
8792623SN/A    // Unbind Float Regs from Rename Map
8802623SN/A    for (RegId reg_id(FloatRegClass, 0); reg_id.index() < TheISA::NumFloatRegs;
8812623SN/A         reg_id.index()++) {
8823349Sbinkertn@umich.edu        PhysRegIdPtr phys_reg = renameMap[tid].lookup(reg_id);
8832657Ssaidi@eecs.umich.edu        scoreboard.unsetReg(phys_reg);
8842657Ssaidi@eecs.umich.edu        freeList.addReg(phys_reg);
8852657Ssaidi@eecs.umich.edu    }
8862657Ssaidi@eecs.umich.edu
8872623SN/A    // Unbind condition-code Regs from Rename Map
8882623SN/A    for (RegId reg_id(CCRegClass, 0); reg_id.index() < TheISA::NumCCRegs;
8892623SN/A         reg_id.index()++) {
8903349Sbinkertn@umich.edu        PhysRegIdPtr phys_reg = renameMap[tid].lookup(reg_id);
8912623SN/A        scoreboard.unsetReg(phys_reg);
8922623SN/A        freeList.addReg(phys_reg);
8932623SN/A    }
8944870Sstever@eecs.umich.edu
8957516Shestness@cs.utexas.edu    // Squash Throughout Pipeline
8967516Shestness@cs.utexas.edu    DynInstPtr inst = commit.rob->readHeadInst(tid);
8972623SN/A    InstSeqNum squash_seq_num = inst->seqNum;
8985099Ssaidi@eecs.umich.edu    fetch.squash(0, squash_seq_num, inst, tid);
8993222Sktlim@umich.edu    decode.squash(tid);
9003184Srdreslin@umich.edu    rename.squash(squash_seq_num, tid);
9015728Sgblack@eecs.umich.edu    iew.squash(tid);
9025728Sgblack@eecs.umich.edu    iew.ldstQueue.squash(squash_seq_num, tid);
9035728Sgblack@eecs.umich.edu    commit.rob->squash(squash_seq_num, tid);
9045728Sgblack@eecs.umich.edu
9055728Sgblack@eecs.umich.edu
9065728Sgblack@eecs.umich.edu    assert(iew.instQueue.getCount(tid) == 0);
9075728Sgblack@eecs.umich.edu    assert(iew.ldstQueue.getCount(tid) == 0);
9085728Sgblack@eecs.umich.edu
9095728Sgblack@eecs.umich.edu    // Reset ROB/IQ/LSQ Entries
9105728Sgblack@eecs.umich.edu
9115728Sgblack@eecs.umich.edu    // Commented out for now.  This should be possible to do by
9125728Sgblack@eecs.umich.edu    // telling all the pipeline stages to drain first, and then
9135728Sgblack@eecs.umich.edu    // checking until the drain completes.  Once the pipeline is
9145728Sgblack@eecs.umich.edu    // drained, call resetEntries(). - 10-09-06 ktlim
9155728Sgblack@eecs.umich.edu/*
9165728Sgblack@eecs.umich.edu    if (activeThreads.size() >= 1) {
9175728Sgblack@eecs.umich.edu        commit.rob->resetEntries();
9185728Sgblack@eecs.umich.edu        iew.resetEntries();
9195728Sgblack@eecs.umich.edu    }
9205728Sgblack@eecs.umich.edu*/
9215728Sgblack@eecs.umich.edu}
9225728Sgblack@eecs.umich.edu
9235728Sgblack@eecs.umich.edutemplate <class Impl>
9245728Sgblack@eecs.umich.eduFault
9255728Sgblack@eecs.umich.eduFullO3CPU<Impl>::hwrei(ThreadID tid)
9265728Sgblack@eecs.umich.edu{
9275728Sgblack@eecs.umich.edu#if THE_ISA == ALPHA_ISA
9282623SN/A    // Need to clear the lock flag upon returning from an interrupt.
9292623SN/A    this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid);
9304998Sgblack@eecs.umich.edu
9314998Sgblack@eecs.umich.edu    this->thread[tid]->kernelStats->hwrei();
9324998Sgblack@eecs.umich.edu
9335001Sgblack@eecs.umich.edu    // FIXME: XXX check for interrupts? XXX
9345001Sgblack@eecs.umich.edu#endif
9355001Sgblack@eecs.umich.edu    return NoFault;
9365001Sgblack@eecs.umich.edu}
9375001Sgblack@eecs.umich.edu
9384998Sgblack@eecs.umich.edutemplate <class Impl>
9395507Sstever@gmail.combool
9405507Sstever@gmail.comFullO3CPU<Impl>::simPalCheck(int palFunc, ThreadID tid)
9416102Sgblack@eecs.umich.edu{
9423170Sstever@eecs.umich.edu#if THE_ISA == ALPHA_ISA
9433170Sstever@eecs.umich.edu    if (this->thread[tid]->kernelStats)
9443170Sstever@eecs.umich.edu        this->thread[tid]->kernelStats->callpal(palFunc,
9452644Sstever@eecs.umich.edu                                                this->threadContexts[tid]);
9462644Sstever@eecs.umich.edu
9472644Sstever@eecs.umich.edu    switch (palFunc) {
9483184Srdreslin@umich.edu      case PAL::halt:
9493227Sktlim@umich.edu        halt();
9503201Shsul@eecs.umich.edu        if (--System::numSystemsRunning == 0)
9513201Shsul@eecs.umich.edu            exitSimLoop("all cpus halted");
9523201Shsul@eecs.umich.edu        break;
9533201Shsul@eecs.umich.edu
9543201Shsul@eecs.umich.edu      case PAL::bpt:
9553201Shsul@eecs.umich.edu      case PAL::bugchk:
9563201Shsul@eecs.umich.edu        if (this->system->breakpoint())
9572644Sstever@eecs.umich.edu            return false;
9582623SN/A        break;
9592623SN/A    }
9602623SN/A#endif
9612798Sktlim@umich.edu    return true;
9622839Sktlim@umich.edu}
9632798Sktlim@umich.edu
9642839Sktlim@umich.edutemplate <class Impl>
9652901Ssaidi@eecs.umich.eduFault
9662839Sktlim@umich.eduFullO3CPU<Impl>::getInterrupts()
9672798Sktlim@umich.edu{
9682623SN/A    // Check if there are any outstanding interrupts
9694192Sktlim@umich.edu    return this->interrupts[0]->getInterrupt(this->threadContexts[0]);
9704192Sktlim@umich.edu}
9714192Sktlim@umich.edu
9724192Sktlim@umich.edutemplate <class Impl>
9734192Sktlim@umich.eduvoid
9744192Sktlim@umich.eduFullO3CPU<Impl>::processInterrupts(const Fault &interrupt)
9754192Sktlim@umich.edu{
9764192Sktlim@umich.edu    // Check for interrupts here.  For now can copy the code that
9775497Ssaidi@eecs.umich.edu    // exists within isa_fullsys_traits.hh.  Also assume that thread 0
9784192Sktlim@umich.edu    // is the one that handles the interrupts.
9794192Sktlim@umich.edu    // @todo: Possibly consolidate the interrupt checking code.
9804192Sktlim@umich.edu    // @todo: Allow other threads to handle interrupts.
9812623SN/A
9823349Sbinkertn@umich.edu    assert(interrupt != NoFault);
9832623SN/A    this->interrupts[0]->updateIntrInfo(this->threadContexts[0]);
9844986Ssaidi@eecs.umich.edu
9853310Srdreslin@umich.edu    DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name());
9864584Ssaidi@eecs.umich.edu    this->trap(interrupt, 0, nullptr);
9872948Ssaidi@eecs.umich.edu}
9885728Sgblack@eecs.umich.edu
9893310Srdreslin@umich.edutemplate <class Impl>
9905728Sgblack@eecs.umich.eduvoid
9913495Sktlim@umich.eduFullO3CPU<Impl>::trap(const Fault &fault, ThreadID tid,
9925728Sgblack@eecs.umich.edu                      const StaticInstPtr &inst)
9932948Ssaidi@eecs.umich.edu{
9943310Srdreslin@umich.edu    // Pass the thread's TC into the invoke method.
9953310Srdreslin@umich.edu    fault->invoke(this->threadContexts[tid], inst);
9964870Sstever@eecs.umich.edu}
9974433Ssaidi@eecs.umich.edu
9984433Ssaidi@eecs.umich.edutemplate <class Impl>
9994433Ssaidi@eecs.umich.eduvoid
10004433Ssaidi@eecs.umich.eduFullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid, Fault *fault)
10014433Ssaidi@eecs.umich.edu{
10024433Ssaidi@eecs.umich.edu    DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
10033310Srdreslin@umich.edu
10044433Ssaidi@eecs.umich.edu    DPRINTF(Activity,"Activity: syscall() called.\n");
10054433Ssaidi@eecs.umich.edu
10062948Ssaidi@eecs.umich.edu    // Temporarily increase this by one to account for the syscall
10072948Ssaidi@eecs.umich.edu    // instruction.
10082948Ssaidi@eecs.umich.edu    ++(this->thread[tid]->funcExeInst);
10092948Ssaidi@eecs.umich.edu
10102948Ssaidi@eecs.umich.edu    // Execute the actual syscall.
10112630SN/A    this->thread[tid]->syscall(callnum, fault);
10122623SN/A
10132623SN/A    // Decrease funcExeInst by one as the normal commit will handle
10142657Ssaidi@eecs.umich.edu    // incrementing it.
10152623SN/A    --(this->thread[tid]->funcExeInst);
10162623SN/A}
10172623SN/A
10182623SN/Atemplate <class Impl>
10192623SN/Avoid
10202623SN/AFullO3CPU<Impl>::serializeThread(CheckpointOut &cp, ThreadID tid) const
10213349Sbinkertn@umich.edu{
10225728Sgblack@eecs.umich.edu    thread[tid]->serialize(cp);
10235728Sgblack@eecs.umich.edu}
10245728Sgblack@eecs.umich.edu
10255728Sgblack@eecs.umich.edutemplate <class Impl>
10265728Sgblack@eecs.umich.eduvoid
10275728Sgblack@eecs.umich.eduFullO3CPU<Impl>::unserializeThread(CheckpointIn &cp, ThreadID tid)
10285728Sgblack@eecs.umich.edu{
10295728Sgblack@eecs.umich.edu    thread[tid]->unserialize(cp);
10305728Sgblack@eecs.umich.edu}
10315728Sgblack@eecs.umich.edu
10325728Sgblack@eecs.umich.edutemplate <class Impl>
10335728Sgblack@eecs.umich.eduDrainState
10345728Sgblack@eecs.umich.eduFullO3CPU<Impl>::drain()
10355728Sgblack@eecs.umich.edu{
10365728Sgblack@eecs.umich.edu    // Deschedule any power gating event (if any)
10375728Sgblack@eecs.umich.edu    deschedulePowerGatingEvent();
10385728Sgblack@eecs.umich.edu
10395728Sgblack@eecs.umich.edu    // If the CPU isn't doing anything, then return immediately.
10405728Sgblack@eecs.umich.edu    if (switchedOut())
10415728Sgblack@eecs.umich.edu        return DrainState::Drained;
10425728Sgblack@eecs.umich.edu
10435728Sgblack@eecs.umich.edu    DPRINTF(Drain, "Draining...\n");
10445728Sgblack@eecs.umich.edu
10455728Sgblack@eecs.umich.edu    // We only need to signal a drain to the commit stage as this
10465728Sgblack@eecs.umich.edu    // initiates squashing controls the draining. Once the commit
10475728Sgblack@eecs.umich.edu    // stage commits an instruction where it is safe to stop, it'll
10485728Sgblack@eecs.umich.edu    // squash the rest of the instructions in the pipeline and force
10495728Sgblack@eecs.umich.edu    // the fetch stage to stall. The pipeline will be drained once all
10505728Sgblack@eecs.umich.edu    // in-flight instructions have retired.
10515728Sgblack@eecs.umich.edu    commit.drain();
10522657Ssaidi@eecs.umich.edu
10533170Sstever@eecs.umich.edu    // Wake the CPU and record activity so everything can drain out if
10542657Ssaidi@eecs.umich.edu    // the CPU was not able to immediately drain.
10552657Ssaidi@eecs.umich.edu    if (!isDrained())  {
10562623SN/A        // If a thread is suspended, wake it up so it can be drained
10572623SN/A        for (auto t : threadContexts) {
10585606Snate@binkert.org            if (t->status() == ThreadContext::Suspended){
10595606Snate@binkert.org                DPRINTF(Drain, "Currently suspended so activate %i \n",
10605606Snate@binkert.org                        t->threadId());
10615103Ssaidi@eecs.umich.edu                t->activate();
10625606Snate@binkert.org                // As the thread is now active, change the power state as well
10635103Ssaidi@eecs.umich.edu                activateContext(t->threadId());
10645103Ssaidi@eecs.umich.edu            }
10655103Ssaidi@eecs.umich.edu        }
10665103Ssaidi@eecs.umich.edu
10675103Ssaidi@eecs.umich.edu        wakeCPU();
10685103Ssaidi@eecs.umich.edu        activityRec.activity();
10695103Ssaidi@eecs.umich.edu
10705103Ssaidi@eecs.umich.edu        DPRINTF(Drain, "CPU not drained\n");
10715103Ssaidi@eecs.umich.edu
10725336Shines@cs.fsu.edu        return DrainState::Draining;
10735103Ssaidi@eecs.umich.edu    } else {
10745103Ssaidi@eecs.umich.edu        DPRINTF(Drain, "CPU is already drained\n");
10755103Ssaidi@eecs.umich.edu        if (tickEvent.scheduled())
10765103Ssaidi@eecs.umich.edu            deschedule(tickEvent);
10772623SN/A
10785315Sstever@gmail.com        // Flush out any old data from the time buffers.  In
10795315Sstever@gmail.com        // particular, there might be some data in flight from the
10805315Sstever@gmail.com        // fetch stage that isn't visible in any of the CPU buffers we
10815315Sstever@gmail.com        // test in isDrained().
10825315Sstever@gmail.com        for (int i = 0; i < timeBuffer.getSize(); ++i) {
10835315Sstever@gmail.com            timeBuffer.advance();
10845315Sstever@gmail.com            fetchQueue.advance();
10852623SN/A            decodeQueue.advance();
10862623SN/A            renameQueue.advance();
10872623SN/A            iewQueue.advance();
10882623SN/A        }
10894762Snate@binkert.org
10904762Snate@binkert.org        drainSanityCheck();
10912623SN/A        return DrainState::Drained;
10925529Snate@binkert.org    }
10935529Snate@binkert.org}
10944762Snate@binkert.org
10954762Snate@binkert.orgtemplate <class Impl>
10962623SN/Abool
10975529Snate@binkert.orgFullO3CPU<Impl>::tryDrain()
10982623SN/A{
1099    if (drainState() != DrainState::Draining || !isDrained())
1100        return false;
1101
1102    if (tickEvent.scheduled())
1103        deschedule(tickEvent);
1104
1105    DPRINTF(Drain, "CPU done draining, processing drain event\n");
1106    signalDrainDone();
1107
1108    return true;
1109}
1110
1111template <class Impl>
1112void
1113FullO3CPU<Impl>::drainSanityCheck() const
1114{
1115    assert(isDrained());
1116    fetch.drainSanityCheck();
1117    decode.drainSanityCheck();
1118    rename.drainSanityCheck();
1119    iew.drainSanityCheck();
1120    commit.drainSanityCheck();
1121}
1122
1123template <class Impl>
1124bool
1125FullO3CPU<Impl>::isDrained() const
1126{
1127    bool drained(true);
1128
1129    if (!instList.empty() || !removeList.empty()) {
1130        DPRINTF(Drain, "Main CPU structures not drained.\n");
1131        drained = false;
1132    }
1133
1134    if (!fetch.isDrained()) {
1135        DPRINTF(Drain, "Fetch not drained.\n");
1136        drained = false;
1137    }
1138
1139    if (!decode.isDrained()) {
1140        DPRINTF(Drain, "Decode not drained.\n");
1141        drained = false;
1142    }
1143
1144    if (!rename.isDrained()) {
1145        DPRINTF(Drain, "Rename not drained.\n");
1146        drained = false;
1147    }
1148
1149    if (!iew.isDrained()) {
1150        DPRINTF(Drain, "IEW not drained.\n");
1151        drained = false;
1152    }
1153
1154    if (!commit.isDrained()) {
1155        DPRINTF(Drain, "Commit not drained.\n");
1156        drained = false;
1157    }
1158
1159    return drained;
1160}
1161
1162template <class Impl>
1163void
1164FullO3CPU<Impl>::commitDrained(ThreadID tid)
1165{
1166    fetch.drainStall(tid);
1167}
1168
1169template <class Impl>
1170void
1171FullO3CPU<Impl>::drainResume()
1172{
1173    if (switchedOut())
1174        return;
1175
1176    DPRINTF(Drain, "Resuming...\n");
1177    verifyMemoryMode();
1178
1179    fetch.drainResume();
1180    commit.drainResume();
1181
1182    _status = Idle;
1183    for (ThreadID i = 0; i < thread.size(); i++) {
1184        if (thread[i]->status() == ThreadContext::Active) {
1185            DPRINTF(Drain, "Activating thread: %i\n", i);
1186            activateThread(i);
1187            _status = Running;
1188        }
1189    }
1190
1191    assert(!tickEvent.scheduled());
1192    if (_status == Running)
1193        schedule(tickEvent, nextCycle());
1194
1195    // Reschedule any power gating event (if any)
1196    schedulePowerGatingEvent();
1197}
1198
1199template <class Impl>
1200void
1201FullO3CPU<Impl>::switchOut()
1202{
1203    DPRINTF(O3CPU, "Switching out\n");
1204    BaseCPU::switchOut();
1205
1206    activityRec.reset();
1207
1208    _status = SwitchedOut;
1209
1210    if (checker)
1211        checker->switchOut();
1212}
1213
1214template <class Impl>
1215void
1216FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
1217{
1218    BaseCPU::takeOverFrom(oldCPU);
1219
1220    fetch.takeOverFrom();
1221    decode.takeOverFrom();
1222    rename.takeOverFrom();
1223    iew.takeOverFrom();
1224    commit.takeOverFrom();
1225
1226    assert(!tickEvent.scheduled());
1227
1228    FullO3CPU<Impl> *oldO3CPU = dynamic_cast<FullO3CPU<Impl>*>(oldCPU);
1229    if (oldO3CPU)
1230        globalSeqNum = oldO3CPU->globalSeqNum;
1231
1232    lastRunningCycle = curCycle();
1233    _status = Idle;
1234}
1235
1236template <class Impl>
1237void
1238FullO3CPU<Impl>::verifyMemoryMode() const
1239{
1240    if (!system->isTimingMode()) {
1241        fatal("The O3 CPU requires the memory system to be in "
1242              "'timing' mode.\n");
1243    }
1244}
1245
1246template <class Impl>
1247TheISA::MiscReg
1248FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid) const
1249{
1250    return this->isa[tid]->readMiscRegNoEffect(misc_reg);
1251}
1252
1253template <class Impl>
1254TheISA::MiscReg
1255FullO3CPU<Impl>::readMiscReg(int misc_reg, ThreadID tid)
1256{
1257    miscRegfileReads++;
1258    return this->isa[tid]->readMiscReg(misc_reg, tcBase(tid));
1259}
1260
1261template <class Impl>
1262void
1263FullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg,
1264        const TheISA::MiscReg &val, ThreadID tid)
1265{
1266    this->isa[tid]->setMiscRegNoEffect(misc_reg, val);
1267}
1268
1269template <class Impl>
1270void
1271FullO3CPU<Impl>::setMiscReg(int misc_reg,
1272        const TheISA::MiscReg &val, ThreadID tid)
1273{
1274    miscRegfileWrites++;
1275    this->isa[tid]->setMiscReg(misc_reg, val, tcBase(tid));
1276}
1277
1278template <class Impl>
1279uint64_t
1280FullO3CPU<Impl>::readIntReg(PhysRegIdPtr phys_reg)
1281{
1282    intRegfileReads++;
1283    return regFile.readIntReg(phys_reg);
1284}
1285
1286template <class Impl>
1287FloatReg
1288FullO3CPU<Impl>::readFloatReg(PhysRegIdPtr phys_reg)
1289{
1290    fpRegfileReads++;
1291    return regFile.readFloatReg(phys_reg);
1292}
1293
1294template <class Impl>
1295FloatRegBits
1296FullO3CPU<Impl>::readFloatRegBits(PhysRegIdPtr phys_reg)
1297{
1298    fpRegfileReads++;
1299    return regFile.readFloatRegBits(phys_reg);
1300}
1301
1302template <class Impl>
1303auto
1304FullO3CPU<Impl>::readVecReg(PhysRegIdPtr phys_reg) const
1305        -> const VecRegContainer&
1306{
1307    vecRegfileReads++;
1308    return regFile.readVecReg(phys_reg);
1309}
1310
1311template <class Impl>
1312auto
1313FullO3CPU<Impl>::getWritableVecReg(PhysRegIdPtr phys_reg)
1314        -> VecRegContainer&
1315{
1316    vecRegfileWrites++;
1317    return regFile.getWritableVecReg(phys_reg);
1318}
1319
1320template <class Impl>
1321auto
1322FullO3CPU<Impl>::readVecElem(PhysRegIdPtr phys_reg) const -> const VecElem&
1323{
1324    vecRegfileReads++;
1325    return regFile.readVecElem(phys_reg);
1326}
1327
1328template <class Impl>
1329CCReg
1330FullO3CPU<Impl>::readCCReg(PhysRegIdPtr phys_reg)
1331{
1332    ccRegfileReads++;
1333    return regFile.readCCReg(phys_reg);
1334}
1335
1336template <class Impl>
1337void
1338FullO3CPU<Impl>::setIntReg(PhysRegIdPtr phys_reg, uint64_t val)
1339{
1340    intRegfileWrites++;
1341    regFile.setIntReg(phys_reg, val);
1342}
1343
1344template <class Impl>
1345void
1346FullO3CPU<Impl>::setFloatReg(PhysRegIdPtr phys_reg, FloatReg val)
1347{
1348    fpRegfileWrites++;
1349    regFile.setFloatReg(phys_reg, val);
1350}
1351
1352template <class Impl>
1353void
1354FullO3CPU<Impl>::setFloatRegBits(PhysRegIdPtr phys_reg, FloatRegBits val)
1355{
1356    fpRegfileWrites++;
1357    regFile.setFloatRegBits(phys_reg, val);
1358}
1359
1360template <class Impl>
1361void
1362FullO3CPU<Impl>::setVecReg(PhysRegIdPtr phys_reg, const VecRegContainer& val)
1363{
1364    vecRegfileWrites++;
1365    regFile.setVecReg(phys_reg, val);
1366}
1367
1368template <class Impl>
1369void
1370FullO3CPU<Impl>::setVecElem(PhysRegIdPtr phys_reg, const VecElem& val)
1371{
1372    vecRegfileWrites++;
1373    regFile.setVecElem(phys_reg, val);
1374}
1375
1376template <class Impl>
1377void
1378FullO3CPU<Impl>::setCCReg(PhysRegIdPtr phys_reg, CCReg val)
1379{
1380    ccRegfileWrites++;
1381    regFile.setCCReg(phys_reg, val);
1382}
1383
1384template <class Impl>
1385uint64_t
1386FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid)
1387{
1388    intRegfileReads++;
1389    PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
1390            RegId(IntRegClass, reg_idx));
1391
1392    return regFile.readIntReg(phys_reg);
1393}
1394
1395template <class Impl>
1396float
1397FullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid)
1398{
1399    fpRegfileReads++;
1400    PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
1401        RegId(FloatRegClass, reg_idx));
1402
1403    return regFile.readFloatReg(phys_reg);
1404}
1405
1406template <class Impl>
1407uint64_t
1408FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid)
1409{
1410    fpRegfileReads++;
1411    PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
1412        RegId(FloatRegClass, reg_idx));
1413
1414    return regFile.readFloatRegBits(phys_reg);
1415}
1416
1417template <class Impl>
1418auto
1419FullO3CPU<Impl>::readArchVecReg(int reg_idx, ThreadID tid) const
1420        -> const VecRegContainer&
1421{
1422    PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
1423                RegId(VecRegClass, reg_idx));
1424    return readVecReg(phys_reg);
1425}
1426
1427template <class Impl>
1428auto
1429FullO3CPU<Impl>::getWritableArchVecReg(int reg_idx, ThreadID tid)
1430        -> VecRegContainer&
1431{
1432    PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
1433                RegId(VecRegClass, reg_idx));
1434    return getWritableVecReg(phys_reg);
1435}
1436
1437template <class Impl>
1438auto
1439FullO3CPU<Impl>::readArchVecElem(const RegIndex& reg_idx, const ElemIndex& ldx,
1440                                 ThreadID tid) const -> const VecElem&
1441{
1442    PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
1443                                RegId(VecRegClass, reg_idx, ldx));
1444    return readVecElem(phys_reg);
1445}
1446
1447template <class Impl>
1448CCReg
1449FullO3CPU<Impl>::readArchCCReg(int reg_idx, ThreadID tid)
1450{
1451    ccRegfileReads++;
1452    PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
1453        RegId(CCRegClass, reg_idx));
1454
1455    return regFile.readCCReg(phys_reg);
1456}
1457
1458template <class Impl>
1459void
1460FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid)
1461{
1462    intRegfileWrites++;
1463    PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
1464            RegId(IntRegClass, reg_idx));
1465
1466    regFile.setIntReg(phys_reg, val);
1467}
1468
1469template <class Impl>
1470void
1471FullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid)
1472{
1473    fpRegfileWrites++;
1474    PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
1475            RegId(FloatRegClass, reg_idx));
1476
1477    regFile.setFloatReg(phys_reg, val);
1478}
1479
1480template <class Impl>
1481void
1482FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid)
1483{
1484    fpRegfileWrites++;
1485    PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
1486            RegId(FloatRegClass, reg_idx));
1487
1488    regFile.setFloatRegBits(phys_reg, val);
1489}
1490
1491template <class Impl>
1492void
1493FullO3CPU<Impl>::setArchVecReg(int reg_idx, const VecRegContainer& val,
1494                               ThreadID tid)
1495{
1496    PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
1497                RegId(VecRegClass, reg_idx));
1498    setVecReg(phys_reg, val);
1499}
1500
1501template <class Impl>
1502void
1503FullO3CPU<Impl>::setArchVecElem(const RegIndex& reg_idx, const ElemIndex& ldx,
1504                                const VecElem& val, ThreadID tid)
1505{
1506    PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
1507                RegId(VecRegClass, reg_idx, ldx));
1508    setVecElem(phys_reg, val);
1509}
1510
1511template <class Impl>
1512void
1513FullO3CPU<Impl>::setArchCCReg(int reg_idx, CCReg val, ThreadID tid)
1514{
1515    ccRegfileWrites++;
1516    PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
1517            RegId(CCRegClass, reg_idx));
1518
1519    regFile.setCCReg(phys_reg, val);
1520}
1521
1522template <class Impl>
1523TheISA::PCState
1524FullO3CPU<Impl>::pcState(ThreadID tid)
1525{
1526    return commit.pcState(tid);
1527}
1528
1529template <class Impl>
1530void
1531FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid)
1532{
1533    commit.pcState(val, tid);
1534}
1535
1536template <class Impl>
1537Addr
1538FullO3CPU<Impl>::instAddr(ThreadID tid)
1539{
1540    return commit.instAddr(tid);
1541}
1542
1543template <class Impl>
1544Addr
1545FullO3CPU<Impl>::nextInstAddr(ThreadID tid)
1546{
1547    return commit.nextInstAddr(tid);
1548}
1549
1550template <class Impl>
1551MicroPC
1552FullO3CPU<Impl>::microPC(ThreadID tid)
1553{
1554    return commit.microPC(tid);
1555}
1556
1557template <class Impl>
1558void
1559FullO3CPU<Impl>::squashFromTC(ThreadID tid)
1560{
1561    this->thread[tid]->noSquashFromTC = true;
1562    this->commit.generateTCEvent(tid);
1563}
1564
1565template <class Impl>
1566typename FullO3CPU<Impl>::ListIt
1567FullO3CPU<Impl>::addInst(DynInstPtr &inst)
1568{
1569    instList.push_back(inst);
1570
1571    return --(instList.end());
1572}
1573
1574template <class Impl>
1575void
1576FullO3CPU<Impl>::instDone(ThreadID tid, DynInstPtr &inst)
1577{
1578    // Keep an instruction count.
1579    if (!inst->isMicroop() || inst->isLastMicroop()) {
1580        thread[tid]->numInst++;
1581        thread[tid]->numInsts++;
1582        committedInsts[tid]++;
1583        system->totalNumInsts++;
1584
1585        // Check for instruction-count-based events.
1586        comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
1587        system->instEventQueue.serviceEvents(system->totalNumInsts);
1588    }
1589    thread[tid]->numOp++;
1590    thread[tid]->numOps++;
1591    committedOps[tid]++;
1592
1593    probeInstCommit(inst->staticInst);
1594}
1595
1596template <class Impl>
1597void
1598FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
1599{
1600    DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s "
1601            "[sn:%lli]\n",
1602            inst->threadNumber, inst->pcState(), inst->seqNum);
1603
1604    removeInstsThisCycle = true;
1605
1606    // Remove the front instruction.
1607    removeList.push(inst->getInstListIt());
1608}
1609
1610template <class Impl>
1611void
1612FullO3CPU<Impl>::removeInstsNotInROB(ThreadID tid)
1613{
1614    DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction"
1615            " list.\n", tid);
1616
1617    ListIt end_it;
1618
1619    bool rob_empty = false;
1620
1621    if (instList.empty()) {
1622        return;
1623    } else if (rob.isEmpty(tid)) {
1624        DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n");
1625        end_it = instList.begin();
1626        rob_empty = true;
1627    } else {
1628        end_it = (rob.readTailInst(tid))->getInstListIt();
1629        DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n");
1630    }
1631
1632    removeInstsThisCycle = true;
1633
1634    ListIt inst_it = instList.end();
1635
1636    inst_it--;
1637
1638    // Walk through the instruction list, removing any instructions
1639    // that were inserted after the given instruction iterator, end_it.
1640    while (inst_it != end_it) {
1641        assert(!instList.empty());
1642
1643        squashInstIt(inst_it, tid);
1644
1645        inst_it--;
1646    }
1647
1648    // If the ROB was empty, then we actually need to remove the first
1649    // instruction as well.
1650    if (rob_empty) {
1651        squashInstIt(inst_it, tid);
1652    }
1653}
1654
1655template <class Impl>
1656void
1657FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid)
1658{
1659    assert(!instList.empty());
1660
1661    removeInstsThisCycle = true;
1662
1663    ListIt inst_iter = instList.end();
1664
1665    inst_iter--;
1666
1667    DPRINTF(O3CPU, "Deleting instructions from instruction "
1668            "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1669            tid, seq_num, (*inst_iter)->seqNum);
1670
1671    while ((*inst_iter)->seqNum > seq_num) {
1672
1673        bool break_loop = (inst_iter == instList.begin());
1674
1675        squashInstIt(inst_iter, tid);
1676
1677        inst_iter--;
1678
1679        if (break_loop)
1680            break;
1681    }
1682}
1683
1684template <class Impl>
1685inline void
1686FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid)
1687{
1688    if ((*instIt)->threadNumber == tid) {
1689        DPRINTF(O3CPU, "Squashing instruction, "
1690                "[tid:%i] [sn:%lli] PC %s\n",
1691                (*instIt)->threadNumber,
1692                (*instIt)->seqNum,
1693                (*instIt)->pcState());
1694
1695        // Mark it as squashed.
1696        (*instIt)->setSquashed();
1697
1698        // @todo: Formulate a consistent method for deleting
1699        // instructions from the instruction list
1700        // Remove the instruction from the list.
1701        removeList.push(instIt);
1702    }
1703}
1704
1705template <class Impl>
1706void
1707FullO3CPU<Impl>::cleanUpRemovedInsts()
1708{
1709    while (!removeList.empty()) {
1710        DPRINTF(O3CPU, "Removing instruction, "
1711                "[tid:%i] [sn:%lli] PC %s\n",
1712                (*removeList.front())->threadNumber,
1713                (*removeList.front())->seqNum,
1714                (*removeList.front())->pcState());
1715
1716        instList.erase(removeList.front());
1717
1718        removeList.pop();
1719    }
1720
1721    removeInstsThisCycle = false;
1722}
1723/*
1724template <class Impl>
1725void
1726FullO3CPU<Impl>::removeAllInsts()
1727{
1728    instList.clear();
1729}
1730*/
1731template <class Impl>
1732void
1733FullO3CPU<Impl>::dumpInsts()
1734{
1735    int num = 0;
1736
1737    ListIt inst_list_it = instList.begin();
1738
1739    cprintf("Dumping Instruction List\n");
1740
1741    while (inst_list_it != instList.end()) {
1742        cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1743                "Squashed:%i\n\n",
1744                num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber,
1745                (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
1746                (*inst_list_it)->isSquashed());
1747        inst_list_it++;
1748        ++num;
1749    }
1750}
1751/*
1752template <class Impl>
1753void
1754FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
1755{
1756    iew.wakeDependents(inst);
1757}
1758*/
1759template <class Impl>
1760void
1761FullO3CPU<Impl>::wakeCPU()
1762{
1763    if (activityRec.active() || tickEvent.scheduled()) {
1764        DPRINTF(Activity, "CPU already running.\n");
1765        return;
1766    }
1767
1768    DPRINTF(Activity, "Waking up CPU\n");
1769
1770    Cycles cycles(curCycle() - lastRunningCycle);
1771    // @todo: This is an oddity that is only here to match the stats
1772    if (cycles > 1) {
1773        --cycles;
1774        idleCycles += cycles;
1775        numCycles += cycles;
1776    }
1777
1778    schedule(tickEvent, clockEdge());
1779}
1780
1781template <class Impl>
1782void
1783FullO3CPU<Impl>::wakeup(ThreadID tid)
1784{
1785    if (this->thread[tid]->status() != ThreadContext::Suspended)
1786        return;
1787
1788    this->wakeCPU();
1789
1790    DPRINTF(Quiesce, "Suspended Processor woken\n");
1791    this->threadContexts[tid]->activate();
1792}
1793
1794template <class Impl>
1795ThreadID
1796FullO3CPU<Impl>::getFreeTid()
1797{
1798    for (ThreadID tid = 0; tid < numThreads; tid++) {
1799        if (!tids[tid]) {
1800            tids[tid] = true;
1801            return tid;
1802        }
1803    }
1804
1805    return InvalidThreadID;
1806}
1807
1808template <class Impl>
1809void
1810FullO3CPU<Impl>::updateThreadPriority()
1811{
1812    if (activeThreads.size() > 1) {
1813        //DEFAULT TO ROUND ROBIN SCHEME
1814        //e.g. Move highest priority to end of thread list
1815        list<ThreadID>::iterator list_begin = activeThreads.begin();
1816
1817        unsigned high_thread = *list_begin;
1818
1819        activeThreads.erase(list_begin);
1820
1821        activeThreads.push_back(high_thread);
1822    }
1823}
1824
1825// Forward declaration of FullO3CPU.
1826template class FullO3CPU<O3CPUImpl>;
1827