cpu.cc revision 3965:b4cab77371ed
12315SN/A/*
28733Sgeoffrey.blake@arm.com * Copyright (c) 2004-2006 The Regents of The University of Michigan
39920Syasuko.eckert@amd.com * All rights reserved.
48733Sgeoffrey.blake@arm.com *
58733Sgeoffrey.blake@arm.com * Redistribution and use in source and binary forms, with or without
68733Sgeoffrey.blake@arm.com * modification, are permitted provided that the following conditions are
78733Sgeoffrey.blake@arm.com * met: redistributions of source code must retain the above copyright
88733Sgeoffrey.blake@arm.com * notice, this list of conditions and the following disclaimer;
98733Sgeoffrey.blake@arm.com * redistributions in binary form must reproduce the above copyright
108733Sgeoffrey.blake@arm.com * notice, this list of conditions and the following disclaimer in the
118733Sgeoffrey.blake@arm.com * documentation and/or other materials provided with the distribution;
128733Sgeoffrey.blake@arm.com * neither the name of the copyright holders nor the names of its
138733Sgeoffrey.blake@arm.com * contributors may be used to endorse or promote products derived from
148733Sgeoffrey.blake@arm.com * this software without specific prior written permission.
152332SN/A *
162315SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172315SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182315SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192315SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202315SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212315SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222315SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232315SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242315SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252315SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262315SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272315SN/A *
282315SN/A * Authors: Kevin Lim
292315SN/A *          Korey Sewell
302315SN/A */
312315SN/A
322315SN/A#include "config/full_system.hh"
332315SN/A#include "config/use_checker.hh"
342315SN/A
352315SN/A#if FULL_SYSTEM
362315SN/A#include "cpu/quiesce_event.hh"
372315SN/A#include "sim/system.hh"
382315SN/A#else
392315SN/A#include "sim/process.hh"
402689Sktlim@umich.edu#endif
412689Sktlim@umich.edu
422315SN/A#include "cpu/activity.hh"
432315SN/A#include "cpu/simple_thread.hh"
442315SN/A#include "cpu/thread_context.hh"
452315SN/A#include "cpu/o3/isa_specific.hh"
462315SN/A#include "cpu/o3/cpu.hh"
472315SN/A
488229Snate@binkert.org#include "sim/root.hh"
492315SN/A#include "sim/stat_control.hh"
502315SN/A
512669Sktlim@umich.edu#if USE_CHECKER
522315SN/A#include "cpu/checker/cpu.hh"
532315SN/A#endif
542315SN/A
558229Snate@binkert.orgusing namespace std;
562683Sktlim@umich.eduusing namespace TheISA;
572315SN/A
588733Sgeoffrey.blake@arm.comBaseO3CPU::BaseO3CPU(Params *params)
598733Sgeoffrey.blake@arm.com    : BaseCPU(params), cpu_id(0)
602315SN/A{
612315SN/A}
622315SN/A
633468Sgblack@eecs.umich.eduvoid
643468Sgblack@eecs.umich.eduBaseO3CPU::regStats()
656022Sgblack@eecs.umich.edu{
663468Sgblack@eecs.umich.edu    BaseCPU::regStats();
672315SN/A}
682315SN/A
692315SN/Atemplate <class Impl>
702680Sktlim@umich.eduFullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
712669Sktlim@umich.edu    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
722315SN/A{
732350SN/A}
742350SN/A
752350SN/Atemplate <class Impl>
762350SN/Avoid
772350SN/AFullO3CPU<Impl>::TickEvent::process()
782350SN/A{
792350SN/A    cpu->tick();
802350SN/A}
812350SN/A
822350SN/Atemplate <class Impl>
832680Sktlim@umich.educonst char *
842683Sktlim@umich.eduFullO3CPU<Impl>::TickEvent::description()
852680Sktlim@umich.edu{
862350SN/A    return "FullO3CPU tick event";
872680Sktlim@umich.edu}
882350SN/A
892315SN/Atemplate <class Impl>
902315SN/AFullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent()
912315SN/A    : Event(&mainEventQueue, CPU_Switch_Pri)
922315SN/A{
932669Sktlim@umich.edu}
942669Sktlim@umich.edu
952315SN/Atemplate <class Impl>
968832SAli.Saidi@ARM.comvoid
978832SAli.Saidi@ARM.comFullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num,
988832SAli.Saidi@ARM.com                                           FullO3CPU<Impl> *thread_cpu)
992315SN/A{
1002315SN/A    tid = thread_num;
1012315SN/A    cpu = thread_cpu;
1025529Snate@binkert.org}
1032315SN/A
1042315SN/Atemplate <class Impl>
1052315SN/Avoid
1062315SN/AFullO3CPU<Impl>::ActivateThreadEvent::process()
1072315SN/A{
1089608Sandreas.hansson@arm.com    cpu->activateThread(tid);
1092679Sktlim@umich.edu}
1109608Sandreas.hansson@arm.com
1112679Sktlim@umich.edutemplate <class Impl>
1129608Sandreas.hansson@arm.comconst char *
1138887Sgeoffrey.blake@arm.comFullO3CPU<Impl>::ActivateThreadEvent::description()
1149176Sandreas.hansson@arm.com{
1159176Sandreas.hansson@arm.com    return "FullO3CPU \"Activate Thread\" event";
1169176Sandreas.hansson@arm.com}
1178887Sgeoffrey.blake@arm.com
1188887Sgeoffrey.blake@arm.comtemplate <class Impl>
1198887Sgeoffrey.blake@arm.comFullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent()
1209608Sandreas.hansson@arm.com    : Event(&mainEventQueue, CPU_Tick_Pri)
1218887Sgeoffrey.blake@arm.com{
1229176Sandreas.hansson@arm.com}
1239176Sandreas.hansson@arm.com
1249176Sandreas.hansson@arm.comtemplate <class Impl>
1258887Sgeoffrey.blake@arm.comvoid
1268887Sgeoffrey.blake@arm.comFullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num,
1272679Sktlim@umich.edu                                           FullO3CPU<Impl> *thread_cpu)
1289176Sandreas.hansson@arm.com{
1299176Sandreas.hansson@arm.com    tid = thread_num;
1309176Sandreas.hansson@arm.com    cpu = thread_cpu;
1319176Sandreas.hansson@arm.com}
1329176Sandreas.hansson@arm.com
1339176Sandreas.hansson@arm.comtemplate <class Impl>
1349608Sandreas.hansson@arm.comvoid
1359608Sandreas.hansson@arm.comFullO3CPU<Impl>::DeallocateContextEvent::process()
1362315SN/A{
1372680Sktlim@umich.edu    cpu->deactivateThread(tid);
1382315SN/A    if (remove)
1396022Sgblack@eecs.umich.edu        cpu->removeThread(tid);
1406022Sgblack@eecs.umich.edu}
1412315SN/A
1422315SN/Atemplate <class Impl>
1432315SN/Aconst char *
1442315SN/AFullO3CPU<Impl>::DeallocateContextEvent::description()
1452315SN/A{
1462315SN/A    return "FullO3CPU \"Deallocate Context\" event";
1478733Sgeoffrey.blake@arm.com}
1488733Sgeoffrey.blake@arm.com
1498733Sgeoffrey.blake@arm.comtemplate <class Impl>
1508733Sgeoffrey.blake@arm.comFullO3CPU<Impl>::FullO3CPU(Params *params)
1512315SN/A    : BaseO3CPU(params),
1522315SN/A#if FULL_SYSTEM
1538733Sgeoffrey.blake@arm.com      itb(params->itb),
1548733Sgeoffrey.blake@arm.com      dtb(params->dtb),
1558733Sgeoffrey.blake@arm.com#endif
1562315SN/A      tickEvent(this),
1572679Sktlim@umich.edu      removeInstsThisCycle(false),
1582679Sktlim@umich.edu      fetch(params),
1592315SN/A      decode(params),
1602315SN/A      rename(params),
1618733Sgeoffrey.blake@arm.com      iew(params),
1622315SN/A      commit(params),
1632315SN/A
1642315SN/A      regFile(params->numPhysIntRegs, params->numPhysFloatRegs),
1652315SN/A
1662315SN/A      freeList(params->numberOfThreads,
1672315SN/A               TheISA::NumIntRegs, params->numPhysIntRegs,
1682315SN/A               TheISA::NumFloatRegs, params->numPhysFloatRegs),
1699176Sandreas.hansson@arm.com
1709176Sandreas.hansson@arm.com      rob(params->numROBEntries, params->squashWidth,
1719176Sandreas.hansson@arm.com          params->smtROBPolicy, params->smtROBThreshold,
1729176Sandreas.hansson@arm.com          params->numberOfThreads),
1739176Sandreas.hansson@arm.com
1748733Sgeoffrey.blake@arm.com      scoreboard(params->numberOfThreads,
1758733Sgeoffrey.blake@arm.com                 TheISA::NumIntRegs, params->numPhysIntRegs,
1768733Sgeoffrey.blake@arm.com                 TheISA::NumFloatRegs, params->numPhysFloatRegs,
1778887Sgeoffrey.blake@arm.com                 TheISA::NumMiscRegs * number_of_threads,
1788887Sgeoffrey.blake@arm.com                 TheISA::ZeroReg),
1798887Sgeoffrey.blake@arm.com
1808887Sgeoffrey.blake@arm.com      timeBuffer(params->backComSize, params->forwardComSize),
1818887Sgeoffrey.blake@arm.com      fetchQueue(params->backComSize, params->forwardComSize),
1828887Sgeoffrey.blake@arm.com      decodeQueue(params->backComSize, params->forwardComSize),
1832315SN/A      renameQueue(params->backComSize, params->forwardComSize),
1842930Sktlim@umich.edu      iewQueue(params->backComSize, params->forwardComSize),
1852315SN/A      activityRec(NumStages,
1862315SN/A                  params->backComSize + params->forwardComSize,
1872315SN/A                  params->activity),
1882315SN/A
1892315SN/A      globalSeqNum(1),
1902315SN/A#if FULL_SYSTEM
1912315SN/A      system(params->system),
1922315SN/A      physmem(system->physmem),
1932315SN/A#endif // FULL_SYSTEM
1942315SN/A      drainCount(0),
1952315SN/A      deferRegistration(params->deferRegistration),
1962315SN/A      numThreads(number_of_threads)
1975543Ssaidi@eecs.umich.edu{
1982315SN/A    if (!deferRegistration) {
1992315SN/A        _status = Running;
2002315SN/A    } else {
2012315SN/A        _status = Idle;
2022315SN/A    }
2032315SN/A
2042315SN/A    checker = NULL;
2052315SN/A
2062315SN/A    if (params->checker) {
2072315SN/A#if USE_CHECKER
2082315SN/A        BaseCPU *temp_checker = params->checker;
2092315SN/A        checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
2103735Sstever@eecs.umich.edu#if FULL_SYSTEM
2112315SN/A        checker->setSystem(params->system);
2122683Sktlim@umich.edu#endif
2132315SN/A#else
2142315SN/A        panic("Checker enabled but not compiled in!");
2153735Sstever@eecs.umich.edu#endif // USE_CHECKER
2162315SN/A    }
2179918Ssteve.reinhardt@amd.com
2182683Sktlim@umich.edu#if !FULL_SYSTEM
2192315SN/A    thread.resize(number_of_threads);
2202315SN/A    tids.resize(number_of_threads);
2213735Sstever@eecs.umich.edu#endif
2222669Sktlim@umich.edu
2239918Ssteve.reinhardt@amd.com    // The stages also need their CPU pointer setup.  However this
2242683Sktlim@umich.edu    // must be done at the upper level CPU because they have pointers
2252315SN/A    // to the upper level CPU, and not this FullO3CPU.
2262315SN/A
2279920Syasuko.eckert@amd.com    // Set up Pointers to the activeThreads list for each stage
2289920Syasuko.eckert@amd.com    fetch.setActiveThreads(&activeThreads);
2299920Syasuko.eckert@amd.com    decode.setActiveThreads(&activeThreads);
2309920Syasuko.eckert@amd.com    rename.setActiveThreads(&activeThreads);
2319920Syasuko.eckert@amd.com    iew.setActiveThreads(&activeThreads);
2329920Syasuko.eckert@amd.com    commit.setActiveThreads(&activeThreads);
2338733Sgeoffrey.blake@arm.com
2348733Sgeoffrey.blake@arm.com    // Give each of the stages the time buffer they will use.
2358733Sgeoffrey.blake@arm.com    fetch.setTimeBuffer(&timeBuffer);
2368733Sgeoffrey.blake@arm.com    decode.setTimeBuffer(&timeBuffer);
2378733Sgeoffrey.blake@arm.com    rename.setTimeBuffer(&timeBuffer);
2388733Sgeoffrey.blake@arm.com    iew.setTimeBuffer(&timeBuffer);
2398733Sgeoffrey.blake@arm.com    commit.setTimeBuffer(&timeBuffer);
2408733Sgeoffrey.blake@arm.com
2413735Sstever@eecs.umich.edu    // Also setup each of the stages' queues.
2422315SN/A    fetch.setFetchQueue(&fetchQueue);
2432683Sktlim@umich.edu    decode.setFetchQueue(&fetchQueue);
2448733Sgeoffrey.blake@arm.com    commit.setFetchQueue(&fetchQueue);
2452315SN/A    decode.setDecodeQueue(&decodeQueue);
2462315SN/A    rename.setDecodeQueue(&decodeQueue);
2473735Sstever@eecs.umich.edu    rename.setRenameQueue(&renameQueue);
2482669Sktlim@umich.edu    iew.setRenameQueue(&renameQueue);
2499918Ssteve.reinhardt@amd.com    iew.setIEWQueue(&iewQueue);
2502683Sktlim@umich.edu    commit.setIEWQueue(&iewQueue);
2518733Sgeoffrey.blake@arm.com    commit.setRenameQueue(&renameQueue);
2522315SN/A
2532315SN/A    commit.setIEWStage(&iew);
2543735Sstever@eecs.umich.edu    rename.setIEWStage(&iew);
2553735Sstever@eecs.umich.edu    rename.setCommitStage(&commit);
2562315SN/A
2579918Ssteve.reinhardt@amd.com#if !FULL_SYSTEM
2582683Sktlim@umich.edu    int active_threads = params->workload.size();
2598733Sgeoffrey.blake@arm.com
2602315SN/A    if (active_threads > Impl::MaxThreads) {
2612315SN/A        panic("Workload Size too large. Increase the 'MaxThreads'"
2629920Syasuko.eckert@amd.com              "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or "
2639920Syasuko.eckert@amd.com              "edit your workload size.");
2649920Syasuko.eckert@amd.com    }
2659920Syasuko.eckert@amd.com#else
2669920Syasuko.eckert@amd.com    int active_threads = 1;
2679920Syasuko.eckert@amd.com#endif
2689920Syasuko.eckert@amd.com
2698733Sgeoffrey.blake@arm.com    //Make Sure That this a Valid Architeture
2708733Sgeoffrey.blake@arm.com    assert(params->numPhysIntRegs   >= numThreads * TheISA::NumIntRegs);
2718733Sgeoffrey.blake@arm.com    assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
2728733Sgeoffrey.blake@arm.com
2738733Sgeoffrey.blake@arm.com    rename.setScoreboard(&scoreboard);
2742669Sktlim@umich.edu    iew.setScoreboard(&scoreboard);
2758733Sgeoffrey.blake@arm.com
2768733Sgeoffrey.blake@arm.com    // Setup the rename map for whichever stages need it.
2778733Sgeoffrey.blake@arm.com    PhysRegIndex lreg_idx = 0;
2788733Sgeoffrey.blake@arm.com    PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs
2798733Sgeoffrey.blake@arm.com
2808733Sgeoffrey.blake@arm.com    for (int tid=0; tid < numThreads; tid++) {
2818733Sgeoffrey.blake@arm.com        bool bindRegs = (tid <= active_threads - 1);
2828733Sgeoffrey.blake@arm.com
2838733Sgeoffrey.blake@arm.com        commitRenameMap[tid].init(TheISA::NumIntRegs,
2848733Sgeoffrey.blake@arm.com                                  params->numPhysIntRegs,
2858733Sgeoffrey.blake@arm.com                                  lreg_idx,            //Index for Logical. Regs
2862315SN/A
2874172Ssaidi@eecs.umich.edu                                  TheISA::NumFloatRegs,
2884172Ssaidi@eecs.umich.edu                                  params->numPhysFloatRegs,
2894172Ssaidi@eecs.umich.edu                                  freg_idx,            //Index for Float Regs
2904172Ssaidi@eecs.umich.edu
2914172Ssaidi@eecs.umich.edu                                  TheISA::NumMiscRegs,
2922315SN/A
2932315SN/A                                  TheISA::ZeroReg,
2942683Sktlim@umich.edu                                  TheISA::ZeroReg,
2952315SN/A
2962315SN/A                                  tid,
2974172Ssaidi@eecs.umich.edu                                  false);
2982315SN/A
2994172Ssaidi@eecs.umich.edu        renameMap[tid].init(TheISA::NumIntRegs,
3004172Ssaidi@eecs.umich.edu                            params->numPhysIntRegs,
3012315SN/A                            lreg_idx,                  //Index for Logical. Regs
3022315SN/A
3033468Sgblack@eecs.umich.edu                            TheISA::NumFloatRegs,
3042315SN/A                            params->numPhysFloatRegs,
3052315SN/A                            freg_idx,                  //Index for Float Regs
3062683Sktlim@umich.edu
3072315SN/A                            TheISA::NumMiscRegs,
3082315SN/A
3098733Sgeoffrey.blake@arm.com                            TheISA::ZeroReg,
3108733Sgeoffrey.blake@arm.com                            TheISA::ZeroReg,
3119918Ssteve.reinhardt@amd.com
3128733Sgeoffrey.blake@arm.com                            tid,
3138733Sgeoffrey.blake@arm.com                            bindRegs);
3148733Sgeoffrey.blake@arm.com
3158733Sgeoffrey.blake@arm.com        activateThreadEvent[tid].init(tid, this);
3168733Sgeoffrey.blake@arm.com        deallocateContextEvent[tid].init(tid, this);
3178733Sgeoffrey.blake@arm.com    }
3189918Ssteve.reinhardt@amd.com
3198733Sgeoffrey.blake@arm.com    rename.setRenameMap(renameMap);
3208733Sgeoffrey.blake@arm.com    commit.setRenameMap(commitRenameMap);
3218888Sgeoffrey.blake@arm.com
3228888Sgeoffrey.blake@arm.com    // Give renameMap & rename stage access to the freeList;
3238888Sgeoffrey.blake@arm.com    for (int i=0; i < numThreads; i++) {
3248888Sgeoffrey.blake@arm.com        renameMap[i].setFreeList(&freeList);
3258888Sgeoffrey.blake@arm.com    }
3268888Sgeoffrey.blake@arm.com    rename.setFreeList(&freeList);
3278888Sgeoffrey.blake@arm.com
3288888Sgeoffrey.blake@arm.com    // Setup the ROB for whichever stages need it.
3298888Sgeoffrey.blake@arm.com    commit.setROB(&rob);
3308888Sgeoffrey.blake@arm.com
3318888Sgeoffrey.blake@arm.com    lastRunningCycle = curTick;
3328888Sgeoffrey.blake@arm.com
3338888Sgeoffrey.blake@arm.com    lastActivatedCycle = -1;
3348888Sgeoffrey.blake@arm.com
3358733Sgeoffrey.blake@arm.com    // Give renameMap & rename stage access to the freeList;
3368733Sgeoffrey.blake@arm.com    //for (int i=0; i < numThreads; i++) {
3378733Sgeoffrey.blake@arm.com        //globalSeqNum[i] = 1;
3388733Sgeoffrey.blake@arm.com        //}
3398733Sgeoffrey.blake@arm.com
3408733Sgeoffrey.blake@arm.com    contextSwitch = false;
3418733Sgeoffrey.blake@arm.com}
3422315SN/A
3435358Sgblack@eecs.umich.edutemplate <class Impl>
3445358Sgblack@eecs.umich.eduFullO3CPU<Impl>::~FullO3CPU()
3455358Sgblack@eecs.umich.edu{
3465358Sgblack@eecs.umich.edu}
3475358Sgblack@eecs.umich.edu
3485358Sgblack@eecs.umich.edutemplate <class Impl>
3495358Sgblack@eecs.umich.eduvoid
3505358Sgblack@eecs.umich.eduFullO3CPU<Impl>::fullCPURegStats()
3515358Sgblack@eecs.umich.edu{
3525358Sgblack@eecs.umich.edu    BaseO3CPU::regStats();
3535358Sgblack@eecs.umich.edu
3545358Sgblack@eecs.umich.edu    // Register any of the O3CPU's stats here.
3555358Sgblack@eecs.umich.edu    timesIdled
3565358Sgblack@eecs.umich.edu        .name(name() + ".timesIdled")
3575358Sgblack@eecs.umich.edu        .desc("Number of times that the entire CPU went into an idle state and"
3585358Sgblack@eecs.umich.edu              " unscheduled itself")
3598733Sgeoffrey.blake@arm.com        .prereq(timesIdled);
3608733Sgeoffrey.blake@arm.com
3618733Sgeoffrey.blake@arm.com    idleCycles
3628733Sgeoffrey.blake@arm.com        .name(name() + ".idleCycles")
3638733Sgeoffrey.blake@arm.com        .desc("Total number of cycles that the CPU has spent unscheduled due "
3648733Sgeoffrey.blake@arm.com              "to idling")
3658733Sgeoffrey.blake@arm.com        .prereq(idleCycles);
3668733Sgeoffrey.blake@arm.com
3675702Ssaidi@eecs.umich.edu    // Number of Instructions simulated
3685702Ssaidi@eecs.umich.edu    // --------------------------------
3698733Sgeoffrey.blake@arm.com    // Should probably be in Base CPU but need templated
3702315SN/A    // MaxThreads so put in here instead
3712332SN/A    committedInsts
3722669Sktlim@umich.edu        .init(numThreads)
3732315SN/A        .name(name() + ".committedInsts")
3742315SN/A        .desc("Number of Instructions Simulated");
3752315SN/A
3762315SN/A    totalCommittedInsts
3772732Sktlim@umich.edu        .name(name() + ".committedInsts_total")
3782315SN/A        .desc("Number of Instructions Simulated");
3792732Sktlim@umich.edu
3808733Sgeoffrey.blake@arm.com    cpi
3818733Sgeoffrey.blake@arm.com        .name(name() + ".cpi")
3822315SN/A        .desc("CPI: Cycles Per Instruction")
3832732Sktlim@umich.edu        .precision(6);
3842732Sktlim@umich.edu    cpi = simTicks / committedInsts;
3852680Sktlim@umich.edu
3862683Sktlim@umich.edu    totalCpi
3872315SN/A        .name(name() + ".cpi_total")
3882315SN/A        .desc("CPI: Total CPI of All Threads")
3892669Sktlim@umich.edu        .precision(6);
3902679Sktlim@umich.edu    totalCpi = simTicks / totalCommittedInsts;
3912315SN/A
3922315SN/A    ipc
3932315SN/A        .name(name() + ".ipc")
3948733Sgeoffrey.blake@arm.com        .desc("IPC: Instructions Per Cycle")
3952315SN/A        .precision(6);
3962315SN/A    ipc =  committedInsts / simTicks;
3972354SN/A
3982732Sktlim@umich.edu    totalIpc
3992315SN/A        .name(name() + ".ipc_total")
4002315SN/A        .desc("IPC: Total IPC of All Threads")
4012315SN/A        .precision(6);
4022315SN/A    totalIpc =  totalCommittedInsts / simTicks;
4032350SN/A
4042350SN/A}
4052350SN/A
4062350SN/Atemplate <class Impl>
4072350SN/APort *
4082350SN/AFullO3CPU<Impl>::getPort(const std::string &if_name, int idx)
4098733Sgeoffrey.blake@arm.com{
4102315SN/A    if (if_name == "dcache_port")
4112315SN/A        return iew.getDcachePort();
4128733Sgeoffrey.blake@arm.com    else if (if_name == "icache_port")
4138733Sgeoffrey.blake@arm.com        return fetch.getIcachePort();
4148733Sgeoffrey.blake@arm.com    else
4152315SN/A        panic("No Such Port\n");
4162315SN/A}
4179023Sgblack@eecs.umich.edu
4182315SN/Atemplate <class Impl>
4192315SN/Avoid
4202840Sktlim@umich.eduFullO3CPU<Impl>::tick()
4212315SN/A{
4222315SN/A    DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
4238733Sgeoffrey.blake@arm.com
4248733Sgeoffrey.blake@arm.com    ++numCycles;
4252732Sktlim@umich.edu
4262315SN/A//    activity = false;
4272315SN/A
4282315SN/A    //Tick each of the stages
4292315SN/A    fetch.tick();
4302315SN/A
4318733Sgeoffrey.blake@arm.com    decode.tick();
4328733Sgeoffrey.blake@arm.com
4332732Sktlim@umich.edu    rename.tick();
4342732Sktlim@umich.edu
4352732Sktlim@umich.edu    iew.tick();
4362732Sktlim@umich.edu
4372360SN/A    commit.tick();
4382732Sktlim@umich.edu
4392360SN/A#if !FULL_SYSTEM
4402354SN/A    doContextSwitch();
4412360SN/A#endif
4422732Sktlim@umich.edu
4432732Sktlim@umich.edu    // Now advance the time buffers
4442732Sktlim@umich.edu    timeBuffer.advance();
4452732Sktlim@umich.edu
4462354SN/A    fetchQueue.advance();
4472354SN/A    decodeQueue.advance();
4482354SN/A    renameQueue.advance();
4492354SN/A    iewQueue.advance();
4502315SN/A
4512315SN/A    activityRec.advance();
4522315SN/A
4532315SN/A    if (removeInstsThisCycle) {
4542315SN/A        cleanUpRemovedInsts();
4552315SN/A    }
456
457    if (!tickEvent.scheduled()) {
458        if (_status == SwitchedOut ||
459            getState() == SimObject::Drained) {
460            DPRINTF(O3CPU, "Switched out!\n");
461            // increment stat
462            lastRunningCycle = curTick;
463        } else if (!activityRec.active() || _status == Idle) {
464            DPRINTF(O3CPU, "Idle!\n");
465            lastRunningCycle = curTick;
466            timesIdled++;
467        } else {
468            tickEvent.schedule(curTick + cycles(1));
469            DPRINTF(O3CPU, "Scheduling next tick!\n");
470        }
471    }
472
473#if !FULL_SYSTEM
474    updateThreadPriority();
475#endif
476
477}
478
479template <class Impl>
480void
481FullO3CPU<Impl>::init()
482{
483    if (!deferRegistration) {
484        registerThreadContexts();
485    }
486
487    // Set inSyscall so that the CPU doesn't squash when initially
488    // setting up registers.
489    for (int i = 0; i < number_of_threads; ++i)
490        thread[i]->inSyscall = true;
491
492    for (int tid=0; tid < number_of_threads; tid++) {
493#if FULL_SYSTEM
494        ThreadContext *src_tc = threadContexts[tid];
495#else
496        ThreadContext *src_tc = thread[tid]->getTC();
497#endif
498        // Threads start in the Suspended State
499        if (src_tc->status() != ThreadContext::Suspended) {
500            continue;
501        }
502
503#if FULL_SYSTEM
504        TheISA::initCPU(src_tc, src_tc->readCpuId());
505#endif
506    }
507
508    // Clear inSyscall.
509    for (int i = 0; i < number_of_threads; ++i)
510        thread[i]->inSyscall = false;
511
512    // Initialize stages.
513    fetch.initStage();
514    iew.initStage();
515    rename.initStage();
516    commit.initStage();
517
518    commit.setThreads(thread);
519}
520
521template <class Impl>
522void
523FullO3CPU<Impl>::activateThread(unsigned tid)
524{
525    list<unsigned>::iterator isActive = find(
526        activeThreads.begin(), activeThreads.end(), tid);
527
528    DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid);
529
530    if (isActive == activeThreads.end()) {
531        DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n",
532                tid);
533
534        activeThreads.push_back(tid);
535    }
536}
537
538template <class Impl>
539void
540FullO3CPU<Impl>::deactivateThread(unsigned tid)
541{
542    //Remove From Active List, if Active
543    list<unsigned>::iterator thread_it =
544        find(activeThreads.begin(), activeThreads.end(), tid);
545
546    DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid);
547
548    if (thread_it != activeThreads.end()) {
549        DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
550                tid);
551        activeThreads.erase(thread_it);
552    }
553}
554
555template <class Impl>
556void
557FullO3CPU<Impl>::activateContext(int tid, int delay)
558{
559#if FULL_SYSTEM
560    // Connect the ThreadContext's memory ports (Functional/Virtual
561    // Ports)
562    threadContexts[tid]->connectMemPorts();
563#endif
564
565    // Needs to set each stage to running as well.
566    if (delay){
567        DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate "
568                "on cycle %d\n", tid, curTick + cycles(delay));
569        scheduleActivateThreadEvent(tid, delay);
570    } else {
571        activateThread(tid);
572    }
573
574    if (lastActivatedCycle < curTick) {
575        scheduleTickEvent(delay);
576
577        // Be sure to signal that there's some activity so the CPU doesn't
578        // deschedule itself.
579        activityRec.activity();
580        fetch.wakeFromQuiesce();
581
582        lastActivatedCycle = curTick;
583
584        _status = Running;
585    }
586}
587
588template <class Impl>
589bool
590FullO3CPU<Impl>::deallocateContext(int tid, bool remove, int delay)
591{
592    // Schedule removal of thread data from CPU
593    if (delay){
594        DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate "
595                "on cycle %d\n", tid, curTick + cycles(delay));
596        scheduleDeallocateContextEvent(tid, remove, delay);
597        return false;
598    } else {
599        deactivateThread(tid);
600        if (remove)
601            removeThread(tid);
602        return true;
603    }
604}
605
606template <class Impl>
607void
608FullO3CPU<Impl>::suspendContext(int tid)
609{
610    DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
611    bool deallocated = deallocateContext(tid, false, 1);
612    // If this was the last thread then unschedule the tick event.
613    if ((activeThreads.size() == 1 && !deallocated) || activeThreads.size() == 0)
614        unscheduleTickEvent();
615    _status = Idle;
616}
617
618template <class Impl>
619void
620FullO3CPU<Impl>::haltContext(int tid)
621{
622    //For now, this is the same as deallocate
623    DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
624    deallocateContext(tid, true, 1);
625}
626
627template <class Impl>
628void
629FullO3CPU<Impl>::insertThread(unsigned tid)
630{
631    DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU");
632    // Will change now that the PC and thread state is internal to the CPU
633    // and not in the ThreadContext.
634#if FULL_SYSTEM
635    ThreadContext *src_tc = system->threadContexts[tid];
636#else
637    ThreadContext *src_tc = tcBase(tid);
638#endif
639
640    //Bind Int Regs to Rename Map
641    for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
642        PhysRegIndex phys_reg = freeList.getIntReg();
643
644        renameMap[tid].setEntry(ireg,phys_reg);
645        scoreboard.setReg(phys_reg);
646    }
647
648    //Bind Float Regs to Rename Map
649    for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
650        PhysRegIndex phys_reg = freeList.getFloatReg();
651
652        renameMap[tid].setEntry(freg,phys_reg);
653        scoreboard.setReg(phys_reg);
654    }
655
656    //Copy Thread Data Into RegFile
657    //this->copyFromTC(tid);
658
659    //Set PC/NPC/NNPC
660    setPC(src_tc->readPC(), tid);
661    setNextPC(src_tc->readNextPC(), tid);
662    setNextNPC(src_tc->readNextNPC(), tid);
663
664    src_tc->setStatus(ThreadContext::Active);
665
666    activateContext(tid,1);
667
668    //Reset ROB/IQ/LSQ Entries
669    commit.rob->resetEntries();
670    iew.resetEntries();
671}
672
673template <class Impl>
674void
675FullO3CPU<Impl>::removeThread(unsigned tid)
676{
677    DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid);
678
679    // Copy Thread Data From RegFile
680    // If thread is suspended, it might be re-allocated
681    //this->copyToTC(tid);
682
683    // Unbind Int Regs from Rename Map
684    for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
685        PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
686
687        scoreboard.unsetReg(phys_reg);
688        freeList.addReg(phys_reg);
689    }
690
691    // Unbind Float Regs from Rename Map
692    for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
693        PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
694
695        scoreboard.unsetReg(phys_reg);
696        freeList.addReg(phys_reg);
697    }
698
699    // Squash Throughout Pipeline
700    InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum;
701    fetch.squash(0, sizeof(TheISA::MachInst), squash_seq_num, true, tid);
702    decode.squash(tid);
703    rename.squash(squash_seq_num, tid);
704    iew.squash(tid);
705    commit.rob->squash(squash_seq_num, tid);
706
707    assert(iew.ldstQueue.getCount(tid) == 0);
708
709    // Reset ROB/IQ/LSQ Entries
710
711    // Commented out for now.  This should be possible to do by
712    // telling all the pipeline stages to drain first, and then
713    // checking until the drain completes.  Once the pipeline is
714    // drained, call resetEntries(). - 10-09-06 ktlim
715/*
716    if (activeThreads.size() >= 1) {
717        commit.rob->resetEntries();
718        iew.resetEntries();
719    }
720*/
721}
722
723
724template <class Impl>
725void
726FullO3CPU<Impl>::activateWhenReady(int tid)
727{
728    DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming"
729            "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
730            tid);
731
732    bool ready = true;
733
734    if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
735        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
736                "Phys. Int. Regs.\n",
737                tid);
738        ready = false;
739    } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
740        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
741                "Phys. Float. Regs.\n",
742                tid);
743        ready = false;
744    } else if (commit.rob->numFreeEntries() >=
745               commit.rob->entryAmount(activeThreads.size() + 1)) {
746        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
747                "ROB entries.\n",
748                tid);
749        ready = false;
750    } else if (iew.instQueue.numFreeEntries() >=
751               iew.instQueue.entryAmount(activeThreads.size() + 1)) {
752        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
753                "IQ entries.\n",
754                tid);
755        ready = false;
756    } else if (iew.ldstQueue.numFreeEntries() >=
757               iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
758        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
759                "LSQ entries.\n",
760                tid);
761        ready = false;
762    }
763
764    if (ready) {
765        insertThread(tid);
766
767        contextSwitch = false;
768
769        cpuWaitList.remove(tid);
770    } else {
771        suspendContext(tid);
772
773        //blocks fetch
774        contextSwitch = true;
775
776        //@todo: dont always add to waitlist
777        //do waitlist
778        cpuWaitList.push_back(tid);
779    }
780}
781
782template <class Impl>
783void
784FullO3CPU<Impl>::serialize(std::ostream &os)
785{
786    SimObject::State so_state = SimObject::getState();
787    SERIALIZE_ENUM(so_state);
788    BaseCPU::serialize(os);
789    nameOut(os, csprintf("%s.tickEvent", name()));
790    tickEvent.serialize(os);
791
792    // Use SimpleThread's ability to checkpoint to make it easier to
793    // write out the registers.  Also make this static so it doesn't
794    // get instantiated multiple times (causes a panic in statistics).
795    static SimpleThread temp;
796
797    for (int i = 0; i < thread.size(); i++) {
798        nameOut(os, csprintf("%s.xc.%i", name(), i));
799        temp.copyTC(thread[i]->getTC());
800        temp.serialize(os);
801    }
802}
803
804template <class Impl>
805void
806FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
807{
808    SimObject::State so_state;
809    UNSERIALIZE_ENUM(so_state);
810    BaseCPU::unserialize(cp, section);
811    tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
812
813    // Use SimpleThread's ability to checkpoint to make it easier to
814    // read in the registers.  Also make this static so it doesn't
815    // get instantiated multiple times (causes a panic in statistics).
816    static SimpleThread temp;
817
818    for (int i = 0; i < thread.size(); i++) {
819        temp.copyTC(thread[i]->getTC());
820        temp.unserialize(cp, csprintf("%s.xc.%i", section, i));
821        thread[i]->getTC()->copyArchRegs(temp.getTC());
822    }
823}
824
825template <class Impl>
826unsigned int
827FullO3CPU<Impl>::drain(Event *drain_event)
828{
829    DPRINTF(O3CPU, "Switching out\n");
830
831    // If the CPU isn't doing anything, then return immediately.
832    if (_status == Idle || _status == SwitchedOut) {
833        return 0;
834    }
835
836    drainCount = 0;
837    fetch.drain();
838    decode.drain();
839    rename.drain();
840    iew.drain();
841    commit.drain();
842
843    // Wake the CPU and record activity so everything can drain out if
844    // the CPU was not able to immediately drain.
845    if (getState() != SimObject::Drained) {
846        // A bit of a hack...set the drainEvent after all the drain()
847        // calls have been made, that way if all of the stages drain
848        // immediately, the signalDrained() function knows not to call
849        // process on the drain event.
850        drainEvent = drain_event;
851
852        wakeCPU();
853        activityRec.activity();
854
855        return 1;
856    } else {
857        return 0;
858    }
859}
860
861template <class Impl>
862void
863FullO3CPU<Impl>::resume()
864{
865    fetch.resume();
866    decode.resume();
867    rename.resume();
868    iew.resume();
869    commit.resume();
870
871    changeState(SimObject::Running);
872
873    if (_status == SwitchedOut || _status == Idle)
874        return;
875
876#if FULL_SYSTEM
877    assert(system->getMemoryMode() == System::Timing);
878#endif
879
880    if (!tickEvent.scheduled())
881        tickEvent.schedule(curTick);
882    _status = Running;
883}
884
885template <class Impl>
886void
887FullO3CPU<Impl>::signalDrained()
888{
889    if (++drainCount == NumStages) {
890        if (tickEvent.scheduled())
891            tickEvent.squash();
892
893        changeState(SimObject::Drained);
894
895        BaseCPU::switchOut();
896
897        if (drainEvent) {
898            drainEvent->process();
899            drainEvent = NULL;
900        }
901    }
902    assert(drainCount <= 5);
903}
904
905template <class Impl>
906void
907FullO3CPU<Impl>::switchOut()
908{
909    fetch.switchOut();
910    rename.switchOut();
911    iew.switchOut();
912    commit.switchOut();
913    instList.clear();
914    while (!removeList.empty()) {
915        removeList.pop();
916    }
917
918    _status = SwitchedOut;
919#if USE_CHECKER
920    if (checker)
921        checker->switchOut();
922#endif
923    if (tickEvent.scheduled())
924        tickEvent.squash();
925}
926
927template <class Impl>
928void
929FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
930{
931    // Flush out any old data from the time buffers.
932    for (int i = 0; i < timeBuffer.getSize(); ++i) {
933        timeBuffer.advance();
934        fetchQueue.advance();
935        decodeQueue.advance();
936        renameQueue.advance();
937        iewQueue.advance();
938    }
939
940    activityRec.reset();
941
942    BaseCPU::takeOverFrom(oldCPU);
943
944    fetch.takeOverFrom();
945    decode.takeOverFrom();
946    rename.takeOverFrom();
947    iew.takeOverFrom();
948    commit.takeOverFrom();
949
950    assert(!tickEvent.scheduled());
951
952    // @todo: Figure out how to properly select the tid to put onto
953    // the active threads list.
954    int tid = 0;
955
956    list<unsigned>::iterator isActive = find(
957        activeThreads.begin(), activeThreads.end(), tid);
958
959    if (isActive == activeThreads.end()) {
960        //May Need to Re-code this if the delay variable is the delay
961        //needed for thread to activate
962        DPRINTF(O3CPU, "Adding Thread %i to active threads list\n",
963                tid);
964
965        activeThreads.push_back(tid);
966    }
967
968    // Set all statuses to active, schedule the CPU's tick event.
969    // @todo: Fix up statuses so this is handled properly
970    for (int i = 0; i < threadContexts.size(); ++i) {
971        ThreadContext *tc = threadContexts[i];
972        if (tc->status() == ThreadContext::Active && _status != Running) {
973            _status = Running;
974            tickEvent.schedule(curTick);
975        }
976    }
977    if (!tickEvent.scheduled())
978        tickEvent.schedule(curTick);
979
980    Port *peer;
981    Port *icachePort = fetch.getIcachePort();
982    if (icachePort->getPeer() == NULL) {
983        peer = oldCPU->getPort("icache_port")->getPeer();
984        icachePort->setPeer(peer);
985    } else {
986        peer = icachePort->getPeer();
987    }
988    peer->setPeer(icachePort);
989
990    Port *dcachePort = iew.getDcachePort();
991    if (dcachePort->getPeer() == NULL) {
992        peer = oldCPU->getPort("dcache_port")->getPeer();
993        dcachePort->setPeer(peer);
994    } else {
995        peer = dcachePort->getPeer();
996    }
997    peer->setPeer(dcachePort);
998}
999
1000template <class Impl>
1001uint64_t
1002FullO3CPU<Impl>::readIntReg(int reg_idx)
1003{
1004    return regFile.readIntReg(reg_idx);
1005}
1006
1007template <class Impl>
1008FloatReg
1009FullO3CPU<Impl>::readFloatReg(int reg_idx, int width)
1010{
1011    return regFile.readFloatReg(reg_idx, width);
1012}
1013
1014template <class Impl>
1015FloatReg
1016FullO3CPU<Impl>::readFloatReg(int reg_idx)
1017{
1018    return regFile.readFloatReg(reg_idx);
1019}
1020
1021template <class Impl>
1022FloatRegBits
1023FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width)
1024{
1025    return regFile.readFloatRegBits(reg_idx, width);
1026}
1027
1028template <class Impl>
1029FloatRegBits
1030FullO3CPU<Impl>::readFloatRegBits(int reg_idx)
1031{
1032    return regFile.readFloatRegBits(reg_idx);
1033}
1034
1035template <class Impl>
1036void
1037FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
1038{
1039    regFile.setIntReg(reg_idx, val);
1040}
1041
1042template <class Impl>
1043void
1044FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width)
1045{
1046    regFile.setFloatReg(reg_idx, val, width);
1047}
1048
1049template <class Impl>
1050void
1051FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val)
1052{
1053    regFile.setFloatReg(reg_idx, val);
1054}
1055
1056template <class Impl>
1057void
1058FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width)
1059{
1060    regFile.setFloatRegBits(reg_idx, val, width);
1061}
1062
1063template <class Impl>
1064void
1065FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
1066{
1067    regFile.setFloatRegBits(reg_idx, val);
1068}
1069
1070template <class Impl>
1071uint64_t
1072FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid)
1073{
1074    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
1075
1076    return regFile.readIntReg(phys_reg);
1077}
1078
1079template <class Impl>
1080float
1081FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid)
1082{
1083    int idx = reg_idx + TheISA::FP_Base_DepTag;
1084    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1085
1086    return regFile.readFloatReg(phys_reg);
1087}
1088
1089template <class Impl>
1090double
1091FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid)
1092{
1093    int idx = reg_idx + TheISA::FP_Base_DepTag;
1094    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1095
1096    return regFile.readFloatReg(phys_reg, 64);
1097}
1098
1099template <class Impl>
1100uint64_t
1101FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid)
1102{
1103    int idx = reg_idx + TheISA::FP_Base_DepTag;
1104    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1105
1106    return regFile.readFloatRegBits(phys_reg);
1107}
1108
1109template <class Impl>
1110void
1111FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid)
1112{
1113    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
1114
1115    regFile.setIntReg(phys_reg, val);
1116}
1117
1118template <class Impl>
1119void
1120FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid)
1121{
1122    int idx = reg_idx + TheISA::FP_Base_DepTag;
1123    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1124
1125    regFile.setFloatReg(phys_reg, val);
1126}
1127
1128template <class Impl>
1129void
1130FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid)
1131{
1132    int idx = reg_idx + TheISA::FP_Base_DepTag;
1133    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1134
1135    regFile.setFloatReg(phys_reg, val, 64);
1136}
1137
1138template <class Impl>
1139void
1140FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid)
1141{
1142    int idx = reg_idx + TheISA::FP_Base_DepTag;
1143    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1144
1145    regFile.setFloatRegBits(phys_reg, val);
1146}
1147
1148template <class Impl>
1149uint64_t
1150FullO3CPU<Impl>::readPC(unsigned tid)
1151{
1152    return commit.readPC(tid);
1153}
1154
1155template <class Impl>
1156void
1157FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid)
1158{
1159    commit.setPC(new_PC, tid);
1160}
1161
1162template <class Impl>
1163uint64_t
1164FullO3CPU<Impl>::readNextPC(unsigned tid)
1165{
1166    return commit.readNextPC(tid);
1167}
1168
1169template <class Impl>
1170void
1171FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid)
1172{
1173    commit.setNextPC(val, tid);
1174}
1175
1176template <class Impl>
1177uint64_t
1178FullO3CPU<Impl>::readNextNPC(unsigned tid)
1179{
1180    return commit.readNextNPC(tid);
1181}
1182
1183template <class Impl>
1184void
1185FullO3CPU<Impl>::setNextNPC(uint64_t val,unsigned tid)
1186{
1187    commit.setNextNPC(val, tid);
1188}
1189
1190template <class Impl>
1191typename FullO3CPU<Impl>::ListIt
1192FullO3CPU<Impl>::addInst(DynInstPtr &inst)
1193{
1194    instList.push_back(inst);
1195
1196    return --(instList.end());
1197}
1198
1199template <class Impl>
1200void
1201FullO3CPU<Impl>::instDone(unsigned tid)
1202{
1203    // Keep an instruction count.
1204    thread[tid]->numInst++;
1205    thread[tid]->numInsts++;
1206    committedInsts[tid]++;
1207    totalCommittedInsts++;
1208
1209    // Check for instruction-count-based events.
1210    comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
1211}
1212
1213template <class Impl>
1214void
1215FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst)
1216{
1217    removeInstsThisCycle = true;
1218
1219    removeList.push(inst->getInstListIt());
1220}
1221
1222template <class Impl>
1223void
1224FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
1225{
1226    DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x "
1227            "[sn:%lli]\n",
1228            inst->threadNumber, inst->readPC(), inst->seqNum);
1229
1230    removeInstsThisCycle = true;
1231
1232    // Remove the front instruction.
1233    removeList.push(inst->getInstListIt());
1234}
1235
1236template <class Impl>
1237void
1238FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid,
1239                                     bool squash_delay_slot,
1240                                     const InstSeqNum &delay_slot_seq_num)
1241{
1242    DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction"
1243            " list.\n", tid);
1244
1245    ListIt end_it;
1246
1247    bool rob_empty = false;
1248
1249    if (instList.empty()) {
1250        return;
1251    } else if (rob.isEmpty(/*tid*/)) {
1252        DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n");
1253        end_it = instList.begin();
1254        rob_empty = true;
1255    } else {
1256        end_it = (rob.readTailInst(tid))->getInstListIt();
1257        DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n");
1258    }
1259
1260    removeInstsThisCycle = true;
1261
1262    ListIt inst_it = instList.end();
1263
1264    inst_it--;
1265
1266    // Walk through the instruction list, removing any instructions
1267    // that were inserted after the given instruction iterator, end_it.
1268    while (inst_it != end_it) {
1269        assert(!instList.empty());
1270
1271#if ISA_HAS_DELAY_SLOT
1272        if(!squash_delay_slot &&
1273           delay_slot_seq_num >= (*inst_it)->seqNum) {
1274            break;
1275        }
1276#endif
1277        squashInstIt(inst_it, tid);
1278
1279        inst_it--;
1280    }
1281
1282    // If the ROB was empty, then we actually need to remove the first
1283    // instruction as well.
1284    if (rob_empty) {
1285        squashInstIt(inst_it, tid);
1286    }
1287}
1288
1289template <class Impl>
1290void
1291FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num,
1292                                  unsigned tid)
1293{
1294    assert(!instList.empty());
1295
1296    removeInstsThisCycle = true;
1297
1298    ListIt inst_iter = instList.end();
1299
1300    inst_iter--;
1301
1302    DPRINTF(O3CPU, "Deleting instructions from instruction "
1303            "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1304            tid, seq_num, (*inst_iter)->seqNum);
1305
1306    while ((*inst_iter)->seqNum > seq_num) {
1307
1308        bool break_loop = (inst_iter == instList.begin());
1309
1310        squashInstIt(inst_iter, tid);
1311
1312        inst_iter--;
1313
1314        if (break_loop)
1315            break;
1316    }
1317}
1318
1319template <class Impl>
1320inline void
1321FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid)
1322{
1323    if ((*instIt)->threadNumber == tid) {
1324        DPRINTF(O3CPU, "Squashing instruction, "
1325                "[tid:%i] [sn:%lli] PC %#x\n",
1326                (*instIt)->threadNumber,
1327                (*instIt)->seqNum,
1328                (*instIt)->readPC());
1329
1330        // Mark it as squashed.
1331        (*instIt)->setSquashed();
1332
1333        // @todo: Formulate a consistent method for deleting
1334        // instructions from the instruction list
1335        // Remove the instruction from the list.
1336        removeList.push(instIt);
1337    }
1338}
1339
1340template <class Impl>
1341void
1342FullO3CPU<Impl>::cleanUpRemovedInsts()
1343{
1344    while (!removeList.empty()) {
1345        DPRINTF(O3CPU, "Removing instruction, "
1346                "[tid:%i] [sn:%lli] PC %#x\n",
1347                (*removeList.front())->threadNumber,
1348                (*removeList.front())->seqNum,
1349                (*removeList.front())->readPC());
1350
1351        instList.erase(removeList.front());
1352
1353        removeList.pop();
1354    }
1355
1356    removeInstsThisCycle = false;
1357}
1358/*
1359template <class Impl>
1360void
1361FullO3CPU<Impl>::removeAllInsts()
1362{
1363    instList.clear();
1364}
1365*/
1366template <class Impl>
1367void
1368FullO3CPU<Impl>::dumpInsts()
1369{
1370    int num = 0;
1371
1372    ListIt inst_list_it = instList.begin();
1373
1374    cprintf("Dumping Instruction List\n");
1375
1376    while (inst_list_it != instList.end()) {
1377        cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1378                "Squashed:%i\n\n",
1379                num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
1380                (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
1381                (*inst_list_it)->isSquashed());
1382        inst_list_it++;
1383        ++num;
1384    }
1385}
1386/*
1387template <class Impl>
1388void
1389FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
1390{
1391    iew.wakeDependents(inst);
1392}
1393*/
1394template <class Impl>
1395void
1396FullO3CPU<Impl>::wakeCPU()
1397{
1398    if (activityRec.active() || tickEvent.scheduled()) {
1399        DPRINTF(Activity, "CPU already running.\n");
1400        return;
1401    }
1402
1403    DPRINTF(Activity, "Waking up CPU\n");
1404
1405    idleCycles += (curTick - 1) - lastRunningCycle;
1406
1407    tickEvent.schedule(curTick);
1408}
1409
1410template <class Impl>
1411int
1412FullO3CPU<Impl>::getFreeTid()
1413{
1414    for (int i=0; i < numThreads; i++) {
1415        if (!tids[i]) {
1416            tids[i] = true;
1417            return i;
1418        }
1419    }
1420
1421    return -1;
1422}
1423
1424template <class Impl>
1425void
1426FullO3CPU<Impl>::doContextSwitch()
1427{
1428    if (contextSwitch) {
1429
1430        //ADD CODE TO DEACTIVE THREAD HERE (???)
1431
1432        for (int tid=0; tid < cpuWaitList.size(); tid++) {
1433            activateWhenReady(tid);
1434        }
1435
1436        if (cpuWaitList.size() == 0)
1437            contextSwitch = true;
1438    }
1439}
1440
1441template <class Impl>
1442void
1443FullO3CPU<Impl>::updateThreadPriority()
1444{
1445    if (activeThreads.size() > 1)
1446    {
1447        //DEFAULT TO ROUND ROBIN SCHEME
1448        //e.g. Move highest priority to end of thread list
1449        list<unsigned>::iterator list_begin = activeThreads.begin();
1450        list<unsigned>::iterator list_end   = activeThreads.end();
1451
1452        unsigned high_thread = *list_begin;
1453
1454        activeThreads.erase(list_begin);
1455
1456        activeThreads.push_back(high_thread);
1457    }
1458}
1459
1460// Forward declaration of FullO3CPU.
1461template class FullO3CPU<O3CPUImpl>;
1462