cpu.cc revision 7897:d9e8b1fd1a9f
1/*
2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
3 * Copyright (c) 2011 Regents of the University of California
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Kevin Lim
30 *          Korey Sewell
31 *          Rick Strong
32 */
33
34#include "config/full_system.hh"
35#include "config/the_isa.hh"
36#include "config/use_checker.hh"
37#include "cpu/activity.hh"
38#include "cpu/simple_thread.hh"
39#include "cpu/thread_context.hh"
40#include "cpu/o3/isa_specific.hh"
41#include "cpu/o3/cpu.hh"
42#include "cpu/o3/thread_context.hh"
43#include "enums/MemoryMode.hh"
44#include "sim/core.hh"
45#include "sim/stat_control.hh"
46
47#if FULL_SYSTEM
48#include "cpu/quiesce_event.hh"
49#include "sim/system.hh"
50#else
51#include "sim/process.hh"
52#endif
53
54#if USE_CHECKER
55#include "cpu/checker/cpu.hh"
56#endif
57
58#if THE_ISA == ALPHA_ISA
59#include "arch/alpha/osfpal.hh"
60#endif
61
62class BaseCPUParams;
63
64using namespace TheISA;
65using namespace std;
66
67BaseO3CPU::BaseO3CPU(BaseCPUParams *params)
68    : BaseCPU(params)
69{
70}
71
72void
73BaseO3CPU::regStats()
74{
75    BaseCPU::regStats();
76}
77
78template <class Impl>
79FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
80    : Event(CPU_Tick_Pri), cpu(c)
81{
82}
83
84template <class Impl>
85void
86FullO3CPU<Impl>::TickEvent::process()
87{
88    cpu->tick();
89}
90
91template <class Impl>
92const char *
93FullO3CPU<Impl>::TickEvent::description() const
94{
95    return "FullO3CPU tick";
96}
97
98template <class Impl>
99FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent()
100    : Event(CPU_Switch_Pri)
101{
102}
103
104template <class Impl>
105void
106FullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num,
107                                           FullO3CPU<Impl> *thread_cpu)
108{
109    tid = thread_num;
110    cpu = thread_cpu;
111}
112
113template <class Impl>
114void
115FullO3CPU<Impl>::ActivateThreadEvent::process()
116{
117    cpu->activateThread(tid);
118}
119
120template <class Impl>
121const char *
122FullO3CPU<Impl>::ActivateThreadEvent::description() const
123{
124    return "FullO3CPU \"Activate Thread\"";
125}
126
127template <class Impl>
128FullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent()
129    : Event(CPU_Tick_Pri), tid(0), remove(false), cpu(NULL)
130{
131}
132
133template <class Impl>
134void
135FullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num,
136                                              FullO3CPU<Impl> *thread_cpu)
137{
138    tid = thread_num;
139    cpu = thread_cpu;
140    remove = false;
141}
142
143template <class Impl>
144void
145FullO3CPU<Impl>::DeallocateContextEvent::process()
146{
147    cpu->deactivateThread(tid);
148    if (remove)
149        cpu->removeThread(tid);
150}
151
152template <class Impl>
153const char *
154FullO3CPU<Impl>::DeallocateContextEvent::description() const
155{
156    return "FullO3CPU \"Deallocate Context\"";
157}
158
159template <class Impl>
160FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
161    : BaseO3CPU(params),
162      itb(params->itb),
163      dtb(params->dtb),
164      tickEvent(this),
165#ifndef NDEBUG
166      instcount(0),
167#endif
168      removeInstsThisCycle(false),
169      fetch(this, params),
170      decode(this, params),
171      rename(this, params),
172      iew(this, params),
173      commit(this, params),
174
175      regFile(this, params->numPhysIntRegs,
176              params->numPhysFloatRegs),
177
178      freeList(params->numThreads,
179               TheISA::NumIntRegs, params->numPhysIntRegs,
180               TheISA::NumFloatRegs, params->numPhysFloatRegs),
181
182      rob(this,
183          params->numROBEntries, params->squashWidth,
184          params->smtROBPolicy, params->smtROBThreshold,
185          params->numThreads),
186
187      scoreboard(params->numThreads,
188                 TheISA::NumIntRegs, params->numPhysIntRegs,
189                 TheISA::NumFloatRegs, params->numPhysFloatRegs,
190                 TheISA::NumMiscRegs * numThreads,
191                 TheISA::ZeroReg),
192
193      timeBuffer(params->backComSize, params->forwardComSize),
194      fetchQueue(params->backComSize, params->forwardComSize),
195      decodeQueue(params->backComSize, params->forwardComSize),
196      renameQueue(params->backComSize, params->forwardComSize),
197      iewQueue(params->backComSize, params->forwardComSize),
198      activityRec(name(), NumStages,
199                  params->backComSize + params->forwardComSize,
200                  params->activity),
201
202      globalSeqNum(1),
203#if FULL_SYSTEM
204      system(params->system),
205#endif // FULL_SYSTEM
206      drainCount(0),
207      deferRegistration(params->defer_registration)
208{
209    if (!deferRegistration) {
210        _status = Running;
211    } else {
212        _status = Idle;
213    }
214
215#if USE_CHECKER
216    if (params->checker) {
217        BaseCPU *temp_checker = params->checker;
218        checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
219#if FULL_SYSTEM
220        checker->setSystem(params->system);
221#endif
222    } else {
223        checker = NULL;
224    }
225#endif // USE_CHECKER
226
227#if !FULL_SYSTEM
228    thread.resize(numThreads);
229    tids.resize(numThreads);
230#endif
231
232    // The stages also need their CPU pointer setup.  However this
233    // must be done at the upper level CPU because they have pointers
234    // to the upper level CPU, and not this FullO3CPU.
235
236    // Set up Pointers to the activeThreads list for each stage
237    fetch.setActiveThreads(&activeThreads);
238    decode.setActiveThreads(&activeThreads);
239    rename.setActiveThreads(&activeThreads);
240    iew.setActiveThreads(&activeThreads);
241    commit.setActiveThreads(&activeThreads);
242
243    // Give each of the stages the time buffer they will use.
244    fetch.setTimeBuffer(&timeBuffer);
245    decode.setTimeBuffer(&timeBuffer);
246    rename.setTimeBuffer(&timeBuffer);
247    iew.setTimeBuffer(&timeBuffer);
248    commit.setTimeBuffer(&timeBuffer);
249
250    // Also setup each of the stages' queues.
251    fetch.setFetchQueue(&fetchQueue);
252    decode.setFetchQueue(&fetchQueue);
253    commit.setFetchQueue(&fetchQueue);
254    decode.setDecodeQueue(&decodeQueue);
255    rename.setDecodeQueue(&decodeQueue);
256    rename.setRenameQueue(&renameQueue);
257    iew.setRenameQueue(&renameQueue);
258    iew.setIEWQueue(&iewQueue);
259    commit.setIEWQueue(&iewQueue);
260    commit.setRenameQueue(&renameQueue);
261
262    commit.setIEWStage(&iew);
263    rename.setIEWStage(&iew);
264    rename.setCommitStage(&commit);
265
266#if !FULL_SYSTEM
267    ThreadID active_threads = params->workload.size();
268
269    if (active_threads > Impl::MaxThreads) {
270        panic("Workload Size too large. Increase the 'MaxThreads'"
271              "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or "
272              "edit your workload size.");
273    }
274#else
275    ThreadID active_threads = 1;
276#endif
277
278    //Make Sure That this a Valid Architeture
279    assert(params->numPhysIntRegs   >= numThreads * TheISA::NumIntRegs);
280    assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
281
282    rename.setScoreboard(&scoreboard);
283    iew.setScoreboard(&scoreboard);
284
285    // Setup the rename map for whichever stages need it.
286    PhysRegIndex lreg_idx = 0;
287    PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs
288
289    for (ThreadID tid = 0; tid < numThreads; tid++) {
290        bool bindRegs = (tid <= active_threads - 1);
291
292        commitRenameMap[tid].init(TheISA::NumIntRegs,
293                                  params->numPhysIntRegs,
294                                  lreg_idx,            //Index for Logical. Regs
295
296                                  TheISA::NumFloatRegs,
297                                  params->numPhysFloatRegs,
298                                  freg_idx,            //Index for Float Regs
299
300                                  TheISA::NumMiscRegs,
301
302                                  TheISA::ZeroReg,
303                                  TheISA::ZeroReg,
304
305                                  tid,
306                                  false);
307
308        renameMap[tid].init(TheISA::NumIntRegs,
309                            params->numPhysIntRegs,
310                            lreg_idx,                  //Index for Logical. Regs
311
312                            TheISA::NumFloatRegs,
313                            params->numPhysFloatRegs,
314                            freg_idx,                  //Index for Float Regs
315
316                            TheISA::NumMiscRegs,
317
318                            TheISA::ZeroReg,
319                            TheISA::ZeroReg,
320
321                            tid,
322                            bindRegs);
323
324        activateThreadEvent[tid].init(tid, this);
325        deallocateContextEvent[tid].init(tid, this);
326    }
327
328    rename.setRenameMap(renameMap);
329    commit.setRenameMap(commitRenameMap);
330
331    // Give renameMap & rename stage access to the freeList;
332    for (ThreadID tid = 0; tid < numThreads; tid++)
333        renameMap[tid].setFreeList(&freeList);
334    rename.setFreeList(&freeList);
335
336    // Setup the ROB for whichever stages need it.
337    commit.setROB(&rob);
338
339    lastRunningCycle = curTick();
340
341    lastActivatedCycle = -1;
342#if 0
343    // Give renameMap & rename stage access to the freeList;
344    for (ThreadID tid = 0; tid < numThreads; tid++)
345        globalSeqNum[tid] = 1;
346#endif
347
348    contextSwitch = false;
349    DPRINTF(O3CPU, "Creating O3CPU object.\n");
350
351    // Setup any thread state.
352    this->thread.resize(this->numThreads);
353
354    for (ThreadID tid = 0; tid < this->numThreads; ++tid) {
355#if FULL_SYSTEM
356        // SMT is not supported in FS mode yet.
357        assert(this->numThreads == 1);
358        this->thread[tid] = new Thread(this, 0);
359#else
360        if (tid < params->workload.size()) {
361            DPRINTF(O3CPU, "Workload[%i] process is %#x",
362                    tid, this->thread[tid]);
363            this->thread[tid] = new typename FullO3CPU<Impl>::Thread(
364                    (typename Impl::O3CPU *)(this),
365                    tid, params->workload[tid]);
366
367            //usedTids[tid] = true;
368            //threadMap[tid] = tid;
369        } else {
370            //Allocate Empty thread so M5 can use later
371            //when scheduling threads to CPU
372            Process* dummy_proc = NULL;
373
374            this->thread[tid] = new typename FullO3CPU<Impl>::Thread(
375                    (typename Impl::O3CPU *)(this),
376                    tid, dummy_proc);
377            //usedTids[tid] = false;
378        }
379#endif // !FULL_SYSTEM
380
381        ThreadContext *tc;
382
383        // Setup the TC that will serve as the interface to the threads/CPU.
384        O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>;
385
386        tc = o3_tc;
387
388        // If we're using a checker, then the TC should be the
389        // CheckerThreadContext.
390#if USE_CHECKER
391        if (params->checker) {
392            tc = new CheckerThreadContext<O3ThreadContext<Impl> >(
393                o3_tc, this->checker);
394        }
395#endif
396
397        o3_tc->cpu = (typename Impl::O3CPU *)(this);
398        assert(o3_tc->cpu);
399        o3_tc->thread = this->thread[tid];
400
401#if FULL_SYSTEM
402        // Setup quiesce event.
403        this->thread[tid]->quiesceEvent = new EndQuiesceEvent(tc);
404#endif
405        // Give the thread the TC.
406        this->thread[tid]->tc = tc;
407
408        // Add the TC to the CPU's list of TC's.
409        this->threadContexts.push_back(tc);
410    }
411
412    for (ThreadID tid = 0; tid < this->numThreads; tid++)
413        this->thread[tid]->setFuncExeInst(0);
414
415    lockAddr = 0;
416    lockFlag = false;
417}
418
419template <class Impl>
420FullO3CPU<Impl>::~FullO3CPU()
421{
422}
423
424template <class Impl>
425void
426FullO3CPU<Impl>::regStats()
427{
428    BaseO3CPU::regStats();
429
430    // Register any of the O3CPU's stats here.
431    timesIdled
432        .name(name() + ".timesIdled")
433        .desc("Number of times that the entire CPU went into an idle state and"
434              " unscheduled itself")
435        .prereq(timesIdled);
436
437    idleCycles
438        .name(name() + ".idleCycles")
439        .desc("Total number of cycles that the CPU has spent unscheduled due "
440              "to idling")
441        .prereq(idleCycles);
442
443    // Number of Instructions simulated
444    // --------------------------------
445    // Should probably be in Base CPU but need templated
446    // MaxThreads so put in here instead
447    committedInsts
448        .init(numThreads)
449        .name(name() + ".committedInsts")
450        .desc("Number of Instructions Simulated");
451
452    totalCommittedInsts
453        .name(name() + ".committedInsts_total")
454        .desc("Number of Instructions Simulated");
455
456    cpi
457        .name(name() + ".cpi")
458        .desc("CPI: Cycles Per Instruction")
459        .precision(6);
460    cpi = numCycles / committedInsts;
461
462    totalCpi
463        .name(name() + ".cpi_total")
464        .desc("CPI: Total CPI of All Threads")
465        .precision(6);
466    totalCpi = numCycles / totalCommittedInsts;
467
468    ipc
469        .name(name() + ".ipc")
470        .desc("IPC: Instructions Per Cycle")
471        .precision(6);
472    ipc =  committedInsts / numCycles;
473
474    totalIpc
475        .name(name() + ".ipc_total")
476        .desc("IPC: Total IPC of All Threads")
477        .precision(6);
478    totalIpc =  totalCommittedInsts / numCycles;
479
480    this->fetch.regStats();
481    this->decode.regStats();
482    this->rename.regStats();
483    this->iew.regStats();
484    this->commit.regStats();
485    this->rob.regStats();
486
487    intRegfileReads
488        .name(name() + ".int_regfile_reads")
489        .desc("number of integer regfile reads")
490        .prereq(intRegfileReads);
491
492    intRegfileWrites
493        .name(name() + ".int_regfile_writes")
494        .desc("number of integer regfile writes")
495        .prereq(intRegfileWrites);
496
497    fpRegfileReads
498        .name(name() + ".fp_regfile_reads")
499        .desc("number of floating regfile reads")
500        .prereq(fpRegfileReads);
501
502    fpRegfileWrites
503        .name(name() + ".fp_regfile_writes")
504        .desc("number of floating regfile writes")
505        .prereq(fpRegfileWrites);
506
507    miscRegfileReads
508        .name(name() + ".misc_regfile_reads")
509        .desc("number of misc regfile reads")
510        .prereq(miscRegfileReads);
511
512    miscRegfileWrites
513        .name(name() + ".misc_regfile_writes")
514        .desc("number of misc regfile writes")
515        .prereq(miscRegfileWrites);
516}
517
518template <class Impl>
519Port *
520FullO3CPU<Impl>::getPort(const std::string &if_name, int idx)
521{
522    if (if_name == "dcache_port")
523        return iew.getDcachePort();
524    else if (if_name == "icache_port")
525        return fetch.getIcachePort();
526    else
527        panic("No Such Port\n");
528}
529
530template <class Impl>
531void
532FullO3CPU<Impl>::tick()
533{
534    DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
535
536    ++numCycles;
537
538//    activity = false;
539
540    //Tick each of the stages
541    fetch.tick();
542
543    decode.tick();
544
545    rename.tick();
546
547    iew.tick();
548
549    commit.tick();
550
551#if !FULL_SYSTEM
552    doContextSwitch();
553#endif
554
555    // Now advance the time buffers
556    timeBuffer.advance();
557
558    fetchQueue.advance();
559    decodeQueue.advance();
560    renameQueue.advance();
561    iewQueue.advance();
562
563    activityRec.advance();
564
565    if (removeInstsThisCycle) {
566        cleanUpRemovedInsts();
567    }
568
569    if (!tickEvent.scheduled()) {
570        if (_status == SwitchedOut ||
571            getState() == SimObject::Drained) {
572            DPRINTF(O3CPU, "Switched out!\n");
573            // increment stat
574            lastRunningCycle = curTick();
575        } else if (!activityRec.active() || _status == Idle) {
576            DPRINTF(O3CPU, "Idle!\n");
577            lastRunningCycle = curTick();
578            timesIdled++;
579        } else {
580            schedule(tickEvent, nextCycle(curTick() + ticks(1)));
581            DPRINTF(O3CPU, "Scheduling next tick!\n");
582        }
583    }
584
585#if !FULL_SYSTEM
586    updateThreadPriority();
587#endif
588}
589
590template <class Impl>
591void
592FullO3CPU<Impl>::init()
593{
594    BaseCPU::init();
595
596    // Set inSyscall so that the CPU doesn't squash when initially
597    // setting up registers.
598    for (ThreadID tid = 0; tid < numThreads; ++tid)
599        thread[tid]->inSyscall = true;
600
601#if FULL_SYSTEM
602    for (ThreadID tid = 0; tid < numThreads; tid++) {
603        ThreadContext *src_tc = threadContexts[tid];
604        TheISA::initCPU(src_tc, src_tc->contextId());
605    }
606#endif
607
608    // Clear inSyscall.
609    for (int tid = 0; tid < numThreads; ++tid)
610        thread[tid]->inSyscall = false;
611
612    // Initialize stages.
613    fetch.initStage();
614    iew.initStage();
615    rename.initStage();
616    commit.initStage();
617
618    commit.setThreads(thread);
619}
620
621template <class Impl>
622void
623FullO3CPU<Impl>::activateThread(ThreadID tid)
624{
625    list<ThreadID>::iterator isActive =
626        std::find(activeThreads.begin(), activeThreads.end(), tid);
627
628    DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid);
629
630    if (isActive == activeThreads.end()) {
631        DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n",
632                tid);
633
634        activeThreads.push_back(tid);
635    }
636}
637
638template <class Impl>
639void
640FullO3CPU<Impl>::deactivateThread(ThreadID tid)
641{
642    //Remove From Active List, if Active
643    list<ThreadID>::iterator thread_it =
644        std::find(activeThreads.begin(), activeThreads.end(), tid);
645
646    DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid);
647
648    if (thread_it != activeThreads.end()) {
649        DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
650                tid);
651        activeThreads.erase(thread_it);
652    }
653}
654
655template <class Impl>
656Counter
657FullO3CPU<Impl>::totalInstructions() const
658{
659    Counter total(0);
660
661    ThreadID size = thread.size();
662    for (ThreadID i = 0; i < size; i++)
663        total += thread[i]->numInst;
664
665    return total;
666}
667
668template <class Impl>
669void
670FullO3CPU<Impl>::activateContext(ThreadID tid, int delay)
671{
672    // Needs to set each stage to running as well.
673    if (delay){
674        DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate "
675                "on cycle %d\n", tid, curTick() + ticks(delay));
676        scheduleActivateThreadEvent(tid, delay);
677    } else {
678        activateThread(tid);
679    }
680
681    if (lastActivatedCycle < curTick()) {
682        scheduleTickEvent(delay);
683
684        // Be sure to signal that there's some activity so the CPU doesn't
685        // deschedule itself.
686        activityRec.activity();
687        fetch.wakeFromQuiesce();
688
689        lastActivatedCycle = curTick();
690
691        _status = Running;
692    }
693}
694
695template <class Impl>
696bool
697FullO3CPU<Impl>::deallocateContext(ThreadID tid, bool remove, int delay)
698{
699    // Schedule removal of thread data from CPU
700    if (delay){
701        DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate "
702                "on cycle %d\n", tid, curTick() + ticks(delay));
703        scheduleDeallocateContextEvent(tid, remove, delay);
704        return false;
705    } else {
706        deactivateThread(tid);
707        if (remove)
708            removeThread(tid);
709        return true;
710    }
711}
712
713template <class Impl>
714void
715FullO3CPU<Impl>::suspendContext(ThreadID tid)
716{
717    DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
718    bool deallocated = deallocateContext(tid, false, 1);
719    // If this was the last thread then unschedule the tick event.
720    if ((activeThreads.size() == 1 && !deallocated) ||
721        activeThreads.size() == 0)
722        unscheduleTickEvent();
723    _status = Idle;
724}
725
726template <class Impl>
727void
728FullO3CPU<Impl>::haltContext(ThreadID tid)
729{
730    //For now, this is the same as deallocate
731    DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
732    deallocateContext(tid, true, 1);
733}
734
735template <class Impl>
736void
737FullO3CPU<Impl>::insertThread(ThreadID tid)
738{
739    DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU");
740    // Will change now that the PC and thread state is internal to the CPU
741    // and not in the ThreadContext.
742#if FULL_SYSTEM
743    ThreadContext *src_tc = system->threadContexts[tid];
744#else
745    ThreadContext *src_tc = tcBase(tid);
746#endif
747
748    //Bind Int Regs to Rename Map
749    for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
750        PhysRegIndex phys_reg = freeList.getIntReg();
751
752        renameMap[tid].setEntry(ireg,phys_reg);
753        scoreboard.setReg(phys_reg);
754    }
755
756    //Bind Float Regs to Rename Map
757    for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
758        PhysRegIndex phys_reg = freeList.getFloatReg();
759
760        renameMap[tid].setEntry(freg,phys_reg);
761        scoreboard.setReg(phys_reg);
762    }
763
764    //Copy Thread Data Into RegFile
765    //this->copyFromTC(tid);
766
767    //Set PC/NPC/NNPC
768    pcState(src_tc->pcState(), tid);
769
770    src_tc->setStatus(ThreadContext::Active);
771
772    activateContext(tid,1);
773
774    //Reset ROB/IQ/LSQ Entries
775    commit.rob->resetEntries();
776    iew.resetEntries();
777}
778
779template <class Impl>
780void
781FullO3CPU<Impl>::removeThread(ThreadID tid)
782{
783    DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid);
784
785    // Copy Thread Data From RegFile
786    // If thread is suspended, it might be re-allocated
787    // this->copyToTC(tid);
788
789
790    // @todo: 2-27-2008: Fix how we free up rename mappings
791    // here to alleviate the case for double-freeing registers
792    // in SMT workloads.
793
794    // Unbind Int Regs from Rename Map
795    for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
796        PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
797
798        scoreboard.unsetReg(phys_reg);
799        freeList.addReg(phys_reg);
800    }
801
802    // Unbind Float Regs from Rename Map
803    for (int freg = TheISA::NumIntRegs; freg < TheISA::NumFloatRegs; freg++) {
804        PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
805
806        scoreboard.unsetReg(phys_reg);
807        freeList.addReg(phys_reg);
808    }
809
810    // Squash Throughout Pipeline
811    InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum;
812    fetch.squash(0, squash_seq_num, tid);
813    decode.squash(tid);
814    rename.squash(squash_seq_num, tid);
815    iew.squash(tid);
816    iew.ldstQueue.squash(squash_seq_num, tid);
817    commit.rob->squash(squash_seq_num, tid);
818
819
820    assert(iew.instQueue.getCount(tid) == 0);
821    assert(iew.ldstQueue.getCount(tid) == 0);
822
823    // Reset ROB/IQ/LSQ Entries
824
825    // Commented out for now.  This should be possible to do by
826    // telling all the pipeline stages to drain first, and then
827    // checking until the drain completes.  Once the pipeline is
828    // drained, call resetEntries(). - 10-09-06 ktlim
829/*
830    if (activeThreads.size() >= 1) {
831        commit.rob->resetEntries();
832        iew.resetEntries();
833    }
834*/
835}
836
837
838template <class Impl>
839void
840FullO3CPU<Impl>::activateWhenReady(ThreadID tid)
841{
842    DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming"
843            "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
844            tid);
845
846    bool ready = true;
847
848    if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
849        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
850                "Phys. Int. Regs.\n",
851                tid);
852        ready = false;
853    } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
854        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
855                "Phys. Float. Regs.\n",
856                tid);
857        ready = false;
858    } else if (commit.rob->numFreeEntries() >=
859               commit.rob->entryAmount(activeThreads.size() + 1)) {
860        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
861                "ROB entries.\n",
862                tid);
863        ready = false;
864    } else if (iew.instQueue.numFreeEntries() >=
865               iew.instQueue.entryAmount(activeThreads.size() + 1)) {
866        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
867                "IQ entries.\n",
868                tid);
869        ready = false;
870    } else if (iew.ldstQueue.numFreeEntries() >=
871               iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
872        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
873                "LSQ entries.\n",
874                tid);
875        ready = false;
876    }
877
878    if (ready) {
879        insertThread(tid);
880
881        contextSwitch = false;
882
883        cpuWaitList.remove(tid);
884    } else {
885        suspendContext(tid);
886
887        //blocks fetch
888        contextSwitch = true;
889
890        //@todo: dont always add to waitlist
891        //do waitlist
892        cpuWaitList.push_back(tid);
893    }
894}
895
896#if FULL_SYSTEM
897template <class Impl>
898Fault
899FullO3CPU<Impl>::hwrei(ThreadID tid)
900{
901#if THE_ISA == ALPHA_ISA
902    // Need to clear the lock flag upon returning from an interrupt.
903    this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid);
904
905    this->thread[tid]->kernelStats->hwrei();
906
907    // FIXME: XXX check for interrupts? XXX
908#endif
909    return NoFault;
910}
911
912template <class Impl>
913bool
914FullO3CPU<Impl>::simPalCheck(int palFunc, ThreadID tid)
915{
916#if THE_ISA == ALPHA_ISA
917    if (this->thread[tid]->kernelStats)
918        this->thread[tid]->kernelStats->callpal(palFunc,
919                                                this->threadContexts[tid]);
920
921    switch (palFunc) {
922      case PAL::halt:
923        halt();
924        if (--System::numSystemsRunning == 0)
925            exitSimLoop("all cpus halted");
926        break;
927
928      case PAL::bpt:
929      case PAL::bugchk:
930        if (this->system->breakpoint())
931            return false;
932        break;
933    }
934#endif
935    return true;
936}
937
938template <class Impl>
939Fault
940FullO3CPU<Impl>::getInterrupts()
941{
942    // Check if there are any outstanding interrupts
943    return this->interrupts->getInterrupt(this->threadContexts[0]);
944}
945
946template <class Impl>
947void
948FullO3CPU<Impl>::processInterrupts(Fault interrupt)
949{
950    // Check for interrupts here.  For now can copy the code that
951    // exists within isa_fullsys_traits.hh.  Also assume that thread 0
952    // is the one that handles the interrupts.
953    // @todo: Possibly consolidate the interrupt checking code.
954    // @todo: Allow other threads to handle interrupts.
955
956    assert(interrupt != NoFault);
957    this->interrupts->updateIntrInfo(this->threadContexts[0]);
958
959    DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name());
960    this->trap(interrupt, 0, NULL);
961}
962
963template <class Impl>
964void
965FullO3CPU<Impl>::updateMemPorts()
966{
967    // Update all ThreadContext's memory ports (Functional/Virtual
968    // Ports)
969    ThreadID size = thread.size();
970    for (ThreadID i = 0; i < size; ++i)
971        thread[i]->connectMemPorts(thread[i]->getTC());
972}
973#endif
974
975template <class Impl>
976void
977FullO3CPU<Impl>::trap(Fault fault, ThreadID tid, StaticInstPtr inst)
978{
979    // Pass the thread's TC into the invoke method.
980    fault->invoke(this->threadContexts[tid], inst);
981}
982
983#if !FULL_SYSTEM
984
985template <class Impl>
986void
987FullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid)
988{
989    DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
990
991    DPRINTF(Activity,"Activity: syscall() called.\n");
992
993    // Temporarily increase this by one to account for the syscall
994    // instruction.
995    ++(this->thread[tid]->funcExeInst);
996
997    // Execute the actual syscall.
998    this->thread[tid]->syscall(callnum);
999
1000    // Decrease funcExeInst by one as the normal commit will handle
1001    // incrementing it.
1002    --(this->thread[tid]->funcExeInst);
1003}
1004
1005#endif
1006
1007template <class Impl>
1008void
1009FullO3CPU<Impl>::serialize(std::ostream &os)
1010{
1011    SimObject::State so_state = SimObject::getState();
1012    SERIALIZE_ENUM(so_state);
1013    BaseCPU::serialize(os);
1014    nameOut(os, csprintf("%s.tickEvent", name()));
1015    tickEvent.serialize(os);
1016
1017    // Use SimpleThread's ability to checkpoint to make it easier to
1018    // write out the registers.  Also make this static so it doesn't
1019    // get instantiated multiple times (causes a panic in statistics).
1020    static SimpleThread temp;
1021
1022    ThreadID size = thread.size();
1023    for (ThreadID i = 0; i < size; i++) {
1024        nameOut(os, csprintf("%s.xc.%i", name(), i));
1025        temp.copyTC(thread[i]->getTC());
1026        temp.serialize(os);
1027    }
1028}
1029
1030template <class Impl>
1031void
1032FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
1033{
1034    SimObject::State so_state;
1035    UNSERIALIZE_ENUM(so_state);
1036    BaseCPU::unserialize(cp, section);
1037    tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
1038
1039    // Use SimpleThread's ability to checkpoint to make it easier to
1040    // read in the registers.  Also make this static so it doesn't
1041    // get instantiated multiple times (causes a panic in statistics).
1042    static SimpleThread temp;
1043
1044    ThreadID size = thread.size();
1045    for (ThreadID i = 0; i < size; i++) {
1046        temp.copyTC(thread[i]->getTC());
1047        temp.unserialize(cp, csprintf("%s.xc.%i", section, i));
1048        thread[i]->getTC()->copyArchRegs(temp.getTC());
1049    }
1050}
1051
1052template <class Impl>
1053unsigned int
1054FullO3CPU<Impl>::drain(Event *drain_event)
1055{
1056    DPRINTF(O3CPU, "Switching out\n");
1057
1058    // If the CPU isn't doing anything, then return immediately.
1059    if (_status == Idle || _status == SwitchedOut) {
1060        return 0;
1061    }
1062
1063    drainCount = 0;
1064    fetch.drain();
1065    decode.drain();
1066    rename.drain();
1067    iew.drain();
1068    commit.drain();
1069
1070    // Wake the CPU and record activity so everything can drain out if
1071    // the CPU was not able to immediately drain.
1072    if (getState() != SimObject::Drained) {
1073        // A bit of a hack...set the drainEvent after all the drain()
1074        // calls have been made, that way if all of the stages drain
1075        // immediately, the signalDrained() function knows not to call
1076        // process on the drain event.
1077        drainEvent = drain_event;
1078
1079        wakeCPU();
1080        activityRec.activity();
1081
1082        return 1;
1083    } else {
1084        return 0;
1085    }
1086}
1087
1088template <class Impl>
1089void
1090FullO3CPU<Impl>::resume()
1091{
1092    fetch.resume();
1093    decode.resume();
1094    rename.resume();
1095    iew.resume();
1096    commit.resume();
1097
1098    changeState(SimObject::Running);
1099
1100    if (_status == SwitchedOut || _status == Idle)
1101        return;
1102
1103#if FULL_SYSTEM
1104    assert(system->getMemoryMode() == Enums::timing);
1105#endif
1106
1107    if (!tickEvent.scheduled())
1108        schedule(tickEvent, nextCycle());
1109    _status = Running;
1110}
1111
1112template <class Impl>
1113void
1114FullO3CPU<Impl>::signalDrained()
1115{
1116    if (++drainCount == NumStages) {
1117        if (tickEvent.scheduled())
1118            tickEvent.squash();
1119
1120        changeState(SimObject::Drained);
1121
1122        BaseCPU::switchOut();
1123
1124        if (drainEvent) {
1125            drainEvent->process();
1126            drainEvent = NULL;
1127        }
1128    }
1129    assert(drainCount <= 5);
1130}
1131
1132template <class Impl>
1133void
1134FullO3CPU<Impl>::switchOut()
1135{
1136    fetch.switchOut();
1137    rename.switchOut();
1138    iew.switchOut();
1139    commit.switchOut();
1140    instList.clear();
1141    while (!removeList.empty()) {
1142        removeList.pop();
1143    }
1144
1145    _status = SwitchedOut;
1146#if USE_CHECKER
1147    if (checker)
1148        checker->switchOut();
1149#endif
1150    if (tickEvent.scheduled())
1151        tickEvent.squash();
1152}
1153
1154template <class Impl>
1155void
1156FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
1157{
1158    // Flush out any old data from the time buffers.
1159    for (int i = 0; i < timeBuffer.getSize(); ++i) {
1160        timeBuffer.advance();
1161        fetchQueue.advance();
1162        decodeQueue.advance();
1163        renameQueue.advance();
1164        iewQueue.advance();
1165    }
1166
1167    activityRec.reset();
1168
1169    BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort());
1170
1171    fetch.takeOverFrom();
1172    decode.takeOverFrom();
1173    rename.takeOverFrom();
1174    iew.takeOverFrom();
1175    commit.takeOverFrom();
1176
1177    assert(!tickEvent.scheduled() || tickEvent.squashed());
1178
1179    // @todo: Figure out how to properly select the tid to put onto
1180    // the active threads list.
1181    ThreadID tid = 0;
1182
1183    list<ThreadID>::iterator isActive =
1184        std::find(activeThreads.begin(), activeThreads.end(), tid);
1185
1186    if (isActive == activeThreads.end()) {
1187        //May Need to Re-code this if the delay variable is the delay
1188        //needed for thread to activate
1189        DPRINTF(O3CPU, "Adding Thread %i to active threads list\n",
1190                tid);
1191
1192        activeThreads.push_back(tid);
1193    }
1194
1195    // Set all statuses to active, schedule the CPU's tick event.
1196    // @todo: Fix up statuses so this is handled properly
1197    ThreadID size = threadContexts.size();
1198    for (ThreadID i = 0; i < size; ++i) {
1199        ThreadContext *tc = threadContexts[i];
1200        if (tc->status() == ThreadContext::Active && _status != Running) {
1201            _status = Running;
1202            reschedule(tickEvent, nextCycle(), true);
1203        }
1204    }
1205    if (!tickEvent.scheduled())
1206        schedule(tickEvent, nextCycle());
1207}
1208
1209template <class Impl>
1210TheISA::MiscReg
1211FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid)
1212{
1213    return this->isa[tid].readMiscRegNoEffect(misc_reg);
1214}
1215
1216template <class Impl>
1217TheISA::MiscReg
1218FullO3CPU<Impl>::readMiscReg(int misc_reg, ThreadID tid)
1219{
1220    miscRegfileReads++;
1221    return this->isa[tid].readMiscReg(misc_reg, tcBase(tid));
1222}
1223
1224template <class Impl>
1225void
1226FullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg,
1227        const TheISA::MiscReg &val, ThreadID tid)
1228{
1229    this->isa[tid].setMiscRegNoEffect(misc_reg, val);
1230}
1231
1232template <class Impl>
1233void
1234FullO3CPU<Impl>::setMiscReg(int misc_reg,
1235        const TheISA::MiscReg &val, ThreadID tid)
1236{
1237    miscRegfileWrites++;
1238    this->isa[tid].setMiscReg(misc_reg, val, tcBase(tid));
1239}
1240
1241template <class Impl>
1242uint64_t
1243FullO3CPU<Impl>::readIntReg(int reg_idx)
1244{
1245    intRegfileReads++;
1246    return regFile.readIntReg(reg_idx);
1247}
1248
1249template <class Impl>
1250FloatReg
1251FullO3CPU<Impl>::readFloatReg(int reg_idx)
1252{
1253    fpRegfileReads++;
1254    return regFile.readFloatReg(reg_idx);
1255}
1256
1257template <class Impl>
1258FloatRegBits
1259FullO3CPU<Impl>::readFloatRegBits(int reg_idx)
1260{
1261    fpRegfileReads++;
1262    return regFile.readFloatRegBits(reg_idx);
1263}
1264
1265template <class Impl>
1266void
1267FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
1268{
1269    intRegfileWrites++;
1270    regFile.setIntReg(reg_idx, val);
1271}
1272
1273template <class Impl>
1274void
1275FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val)
1276{
1277    fpRegfileWrites++;
1278    regFile.setFloatReg(reg_idx, val);
1279}
1280
1281template <class Impl>
1282void
1283FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
1284{
1285    fpRegfileWrites++;
1286    regFile.setFloatRegBits(reg_idx, val);
1287}
1288
1289template <class Impl>
1290uint64_t
1291FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid)
1292{
1293    intRegfileReads++;
1294    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
1295
1296    return regFile.readIntReg(phys_reg);
1297}
1298
1299template <class Impl>
1300float
1301FullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid)
1302{
1303    fpRegfileReads++;
1304    int idx = reg_idx + TheISA::NumIntRegs;
1305    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1306
1307    return regFile.readFloatReg(phys_reg);
1308}
1309
1310template <class Impl>
1311uint64_t
1312FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid)
1313{
1314    fpRegfileReads++;
1315    int idx = reg_idx + TheISA::NumIntRegs;
1316    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1317
1318    return regFile.readFloatRegBits(phys_reg);
1319}
1320
1321template <class Impl>
1322void
1323FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid)
1324{
1325    intRegfileWrites++;
1326    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
1327
1328    regFile.setIntReg(phys_reg, val);
1329}
1330
1331template <class Impl>
1332void
1333FullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid)
1334{
1335    fpRegfileWrites++;
1336    int idx = reg_idx + TheISA::NumIntRegs;
1337    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1338
1339    regFile.setFloatReg(phys_reg, val);
1340}
1341
1342template <class Impl>
1343void
1344FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid)
1345{
1346    fpRegfileWrites++;
1347    int idx = reg_idx + TheISA::NumIntRegs;
1348    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1349
1350    regFile.setFloatRegBits(phys_reg, val);
1351}
1352
1353template <class Impl>
1354TheISA::PCState
1355FullO3CPU<Impl>::pcState(ThreadID tid)
1356{
1357    return commit.pcState(tid);
1358}
1359
1360template <class Impl>
1361void
1362FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid)
1363{
1364    commit.pcState(val, tid);
1365}
1366
1367template <class Impl>
1368Addr
1369FullO3CPU<Impl>::instAddr(ThreadID tid)
1370{
1371    return commit.instAddr(tid);
1372}
1373
1374template <class Impl>
1375Addr
1376FullO3CPU<Impl>::nextInstAddr(ThreadID tid)
1377{
1378    return commit.nextInstAddr(tid);
1379}
1380
1381template <class Impl>
1382MicroPC
1383FullO3CPU<Impl>::microPC(ThreadID tid)
1384{
1385    return commit.microPC(tid);
1386}
1387
1388template <class Impl>
1389void
1390FullO3CPU<Impl>::squashFromTC(ThreadID tid)
1391{
1392    this->thread[tid]->inSyscall = true;
1393    this->commit.generateTCEvent(tid);
1394}
1395
1396template <class Impl>
1397typename FullO3CPU<Impl>::ListIt
1398FullO3CPU<Impl>::addInst(DynInstPtr &inst)
1399{
1400    instList.push_back(inst);
1401
1402    return --(instList.end());
1403}
1404
1405template <class Impl>
1406void
1407FullO3CPU<Impl>::instDone(ThreadID tid)
1408{
1409    // Keep an instruction count.
1410    thread[tid]->numInst++;
1411    thread[tid]->numInsts++;
1412    committedInsts[tid]++;
1413    totalCommittedInsts++;
1414    system->totalNumInsts++;
1415    // Check for instruction-count-based events.
1416    comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
1417    system->instEventQueue.serviceEvents(system->totalNumInsts);
1418}
1419
1420template <class Impl>
1421void
1422FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst)
1423{
1424    removeInstsThisCycle = true;
1425
1426    removeList.push(inst->getInstListIt());
1427}
1428
1429template <class Impl>
1430void
1431FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
1432{
1433    DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s "
1434            "[sn:%lli]\n",
1435            inst->threadNumber, inst->pcState(), inst->seqNum);
1436
1437    removeInstsThisCycle = true;
1438
1439    // Remove the front instruction.
1440    removeList.push(inst->getInstListIt());
1441}
1442
1443template <class Impl>
1444void
1445FullO3CPU<Impl>::removeInstsNotInROB(ThreadID tid)
1446{
1447    DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction"
1448            " list.\n", tid);
1449
1450    ListIt end_it;
1451
1452    bool rob_empty = false;
1453
1454    if (instList.empty()) {
1455        return;
1456    } else if (rob.isEmpty(/*tid*/)) {
1457        DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n");
1458        end_it = instList.begin();
1459        rob_empty = true;
1460    } else {
1461        end_it = (rob.readTailInst(tid))->getInstListIt();
1462        DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n");
1463    }
1464
1465    removeInstsThisCycle = true;
1466
1467    ListIt inst_it = instList.end();
1468
1469    inst_it--;
1470
1471    // Walk through the instruction list, removing any instructions
1472    // that were inserted after the given instruction iterator, end_it.
1473    while (inst_it != end_it) {
1474        assert(!instList.empty());
1475
1476        squashInstIt(inst_it, tid);
1477
1478        inst_it--;
1479    }
1480
1481    // If the ROB was empty, then we actually need to remove the first
1482    // instruction as well.
1483    if (rob_empty) {
1484        squashInstIt(inst_it, tid);
1485    }
1486}
1487
1488template <class Impl>
1489void
1490FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid)
1491{
1492    assert(!instList.empty());
1493
1494    removeInstsThisCycle = true;
1495
1496    ListIt inst_iter = instList.end();
1497
1498    inst_iter--;
1499
1500    DPRINTF(O3CPU, "Deleting instructions from instruction "
1501            "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1502            tid, seq_num, (*inst_iter)->seqNum);
1503
1504    while ((*inst_iter)->seqNum > seq_num) {
1505
1506        bool break_loop = (inst_iter == instList.begin());
1507
1508        squashInstIt(inst_iter, tid);
1509
1510        inst_iter--;
1511
1512        if (break_loop)
1513            break;
1514    }
1515}
1516
1517template <class Impl>
1518inline void
1519FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid)
1520{
1521    if ((*instIt)->threadNumber == tid) {
1522        DPRINTF(O3CPU, "Squashing instruction, "
1523                "[tid:%i] [sn:%lli] PC %s\n",
1524                (*instIt)->threadNumber,
1525                (*instIt)->seqNum,
1526                (*instIt)->pcState());
1527
1528        // Mark it as squashed.
1529        (*instIt)->setSquashed();
1530
1531        // @todo: Formulate a consistent method for deleting
1532        // instructions from the instruction list
1533        // Remove the instruction from the list.
1534        removeList.push(instIt);
1535    }
1536}
1537
1538template <class Impl>
1539void
1540FullO3CPU<Impl>::cleanUpRemovedInsts()
1541{
1542    while (!removeList.empty()) {
1543        DPRINTF(O3CPU, "Removing instruction, "
1544                "[tid:%i] [sn:%lli] PC %s\n",
1545                (*removeList.front())->threadNumber,
1546                (*removeList.front())->seqNum,
1547                (*removeList.front())->pcState());
1548
1549        instList.erase(removeList.front());
1550
1551        removeList.pop();
1552    }
1553
1554    removeInstsThisCycle = false;
1555}
1556/*
1557template <class Impl>
1558void
1559FullO3CPU<Impl>::removeAllInsts()
1560{
1561    instList.clear();
1562}
1563*/
1564template <class Impl>
1565void
1566FullO3CPU<Impl>::dumpInsts()
1567{
1568    int num = 0;
1569
1570    ListIt inst_list_it = instList.begin();
1571
1572    cprintf("Dumping Instruction List\n");
1573
1574    while (inst_list_it != instList.end()) {
1575        cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1576                "Squashed:%i\n\n",
1577                num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber,
1578                (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
1579                (*inst_list_it)->isSquashed());
1580        inst_list_it++;
1581        ++num;
1582    }
1583}
1584/*
1585template <class Impl>
1586void
1587FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
1588{
1589    iew.wakeDependents(inst);
1590}
1591*/
1592template <class Impl>
1593void
1594FullO3CPU<Impl>::wakeCPU()
1595{
1596    if (activityRec.active() || tickEvent.scheduled()) {
1597        DPRINTF(Activity, "CPU already running.\n");
1598        return;
1599    }
1600
1601    DPRINTF(Activity, "Waking up CPU\n");
1602
1603    idleCycles += tickToCycles((curTick() - 1) - lastRunningCycle);
1604    numCycles += tickToCycles((curTick() - 1) - lastRunningCycle);
1605
1606    schedule(tickEvent, nextCycle());
1607}
1608
1609#if FULL_SYSTEM
1610template <class Impl>
1611void
1612FullO3CPU<Impl>::wakeup()
1613{
1614    if (this->thread[0]->status() != ThreadContext::Suspended)
1615        return;
1616
1617    this->wakeCPU();
1618
1619    DPRINTF(Quiesce, "Suspended Processor woken\n");
1620    this->threadContexts[0]->activate();
1621}
1622#endif
1623
1624template <class Impl>
1625ThreadID
1626FullO3CPU<Impl>::getFreeTid()
1627{
1628    for (ThreadID tid = 0; tid < numThreads; tid++) {
1629        if (!tids[tid]) {
1630            tids[tid] = true;
1631            return tid;
1632        }
1633    }
1634
1635    return InvalidThreadID;
1636}
1637
1638template <class Impl>
1639void
1640FullO3CPU<Impl>::doContextSwitch()
1641{
1642    if (contextSwitch) {
1643
1644        //ADD CODE TO DEACTIVE THREAD HERE (???)
1645
1646        ThreadID size = cpuWaitList.size();
1647        for (ThreadID tid = 0; tid < size; tid++) {
1648            activateWhenReady(tid);
1649        }
1650
1651        if (cpuWaitList.size() == 0)
1652            contextSwitch = true;
1653    }
1654}
1655
1656template <class Impl>
1657void
1658FullO3CPU<Impl>::updateThreadPriority()
1659{
1660    if (activeThreads.size() > 1) {
1661        //DEFAULT TO ROUND ROBIN SCHEME
1662        //e.g. Move highest priority to end of thread list
1663        list<ThreadID>::iterator list_begin = activeThreads.begin();
1664        list<ThreadID>::iterator list_end   = activeThreads.end();
1665
1666        unsigned high_thread = *list_begin;
1667
1668        activeThreads.erase(list_begin);
1669
1670        activeThreads.push_back(high_thread);
1671    }
1672}
1673
1674// Forward declaration of FullO3CPU.
1675template class FullO3CPU<O3CPUImpl>;
1676