cpu.cc revision 8229:78bf55f23338
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/o3/cpu.hh"
38#include "cpu/o3/isa_specific.hh"
39#include "cpu/o3/thread_context.hh"
40#include "cpu/activity.hh"
41#include "cpu/simple_thread.hh"
42#include "cpu/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    DynInstPtr inst = commit.rob->readHeadInst(tid);
812    InstSeqNum squash_seq_num = inst->seqNum;
813    fetch.squash(0, squash_seq_num, inst, tid);
814    decode.squash(tid);
815    rename.squash(squash_seq_num, tid);
816    iew.squash(tid);
817    iew.ldstQueue.squash(squash_seq_num, tid);
818    commit.rob->squash(squash_seq_num, tid);
819
820
821    assert(iew.instQueue.getCount(tid) == 0);
822    assert(iew.ldstQueue.getCount(tid) == 0);
823
824    // Reset ROB/IQ/LSQ Entries
825
826    // Commented out for now.  This should be possible to do by
827    // telling all the pipeline stages to drain first, and then
828    // checking until the drain completes.  Once the pipeline is
829    // drained, call resetEntries(). - 10-09-06 ktlim
830/*
831    if (activeThreads.size() >= 1) {
832        commit.rob->resetEntries();
833        iew.resetEntries();
834    }
835*/
836}
837
838
839template <class Impl>
840void
841FullO3CPU<Impl>::activateWhenReady(ThreadID tid)
842{
843    DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming"
844            "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
845            tid);
846
847    bool ready = true;
848
849    if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
850        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
851                "Phys. Int. Regs.\n",
852                tid);
853        ready = false;
854    } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
855        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
856                "Phys. Float. Regs.\n",
857                tid);
858        ready = false;
859    } else if (commit.rob->numFreeEntries() >=
860               commit.rob->entryAmount(activeThreads.size() + 1)) {
861        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
862                "ROB entries.\n",
863                tid);
864        ready = false;
865    } else if (iew.instQueue.numFreeEntries() >=
866               iew.instQueue.entryAmount(activeThreads.size() + 1)) {
867        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
868                "IQ entries.\n",
869                tid);
870        ready = false;
871    } else if (iew.ldstQueue.numFreeEntries() >=
872               iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
873        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
874                "LSQ entries.\n",
875                tid);
876        ready = false;
877    }
878
879    if (ready) {
880        insertThread(tid);
881
882        contextSwitch = false;
883
884        cpuWaitList.remove(tid);
885    } else {
886        suspendContext(tid);
887
888        //blocks fetch
889        contextSwitch = true;
890
891        //@todo: dont always add to waitlist
892        //do waitlist
893        cpuWaitList.push_back(tid);
894    }
895}
896
897#if FULL_SYSTEM
898template <class Impl>
899Fault
900FullO3CPU<Impl>::hwrei(ThreadID tid)
901{
902#if THE_ISA == ALPHA_ISA
903    // Need to clear the lock flag upon returning from an interrupt.
904    this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid);
905
906    this->thread[tid]->kernelStats->hwrei();
907
908    // FIXME: XXX check for interrupts? XXX
909#endif
910    return NoFault;
911}
912
913template <class Impl>
914bool
915FullO3CPU<Impl>::simPalCheck(int palFunc, ThreadID tid)
916{
917#if THE_ISA == ALPHA_ISA
918    if (this->thread[tid]->kernelStats)
919        this->thread[tid]->kernelStats->callpal(palFunc,
920                                                this->threadContexts[tid]);
921
922    switch (palFunc) {
923      case PAL::halt:
924        halt();
925        if (--System::numSystemsRunning == 0)
926            exitSimLoop("all cpus halted");
927        break;
928
929      case PAL::bpt:
930      case PAL::bugchk:
931        if (this->system->breakpoint())
932            return false;
933        break;
934    }
935#endif
936    return true;
937}
938
939template <class Impl>
940Fault
941FullO3CPU<Impl>::getInterrupts()
942{
943    // Check if there are any outstanding interrupts
944    return this->interrupts->getInterrupt(this->threadContexts[0]);
945}
946
947template <class Impl>
948void
949FullO3CPU<Impl>::processInterrupts(Fault interrupt)
950{
951    // Check for interrupts here.  For now can copy the code that
952    // exists within isa_fullsys_traits.hh.  Also assume that thread 0
953    // is the one that handles the interrupts.
954    // @todo: Possibly consolidate the interrupt checking code.
955    // @todo: Allow other threads to handle interrupts.
956
957    assert(interrupt != NoFault);
958    this->interrupts->updateIntrInfo(this->threadContexts[0]);
959
960    DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name());
961    this->trap(interrupt, 0, NULL);
962}
963
964template <class Impl>
965void
966FullO3CPU<Impl>::updateMemPorts()
967{
968    // Update all ThreadContext's memory ports (Functional/Virtual
969    // Ports)
970    ThreadID size = thread.size();
971    for (ThreadID i = 0; i < size; ++i)
972        thread[i]->connectMemPorts(thread[i]->getTC());
973}
974#endif
975
976template <class Impl>
977void
978FullO3CPU<Impl>::trap(Fault fault, ThreadID tid, StaticInstPtr inst)
979{
980    // Pass the thread's TC into the invoke method.
981    fault->invoke(this->threadContexts[tid], inst);
982}
983
984#if !FULL_SYSTEM
985
986template <class Impl>
987void
988FullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid)
989{
990    DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
991
992    DPRINTF(Activity,"Activity: syscall() called.\n");
993
994    // Temporarily increase this by one to account for the syscall
995    // instruction.
996    ++(this->thread[tid]->funcExeInst);
997
998    // Execute the actual syscall.
999    this->thread[tid]->syscall(callnum);
1000
1001    // Decrease funcExeInst by one as the normal commit will handle
1002    // incrementing it.
1003    --(this->thread[tid]->funcExeInst);
1004}
1005
1006#endif
1007
1008template <class Impl>
1009void
1010FullO3CPU<Impl>::serialize(std::ostream &os)
1011{
1012    SimObject::State so_state = SimObject::getState();
1013    SERIALIZE_ENUM(so_state);
1014    BaseCPU::serialize(os);
1015    nameOut(os, csprintf("%s.tickEvent", name()));
1016    tickEvent.serialize(os);
1017
1018    // Use SimpleThread's ability to checkpoint to make it easier to
1019    // write out the registers.  Also make this static so it doesn't
1020    // get instantiated multiple times (causes a panic in statistics).
1021    static SimpleThread temp;
1022
1023    ThreadID size = thread.size();
1024    for (ThreadID i = 0; i < size; i++) {
1025        nameOut(os, csprintf("%s.xc.%i", name(), i));
1026        temp.copyTC(thread[i]->getTC());
1027        temp.serialize(os);
1028    }
1029}
1030
1031template <class Impl>
1032void
1033FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
1034{
1035    SimObject::State so_state;
1036    UNSERIALIZE_ENUM(so_state);
1037    BaseCPU::unserialize(cp, section);
1038    tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
1039
1040    // Use SimpleThread's ability to checkpoint to make it easier to
1041    // read in the registers.  Also make this static so it doesn't
1042    // get instantiated multiple times (causes a panic in statistics).
1043    static SimpleThread temp;
1044
1045    ThreadID size = thread.size();
1046    for (ThreadID i = 0; i < size; i++) {
1047        temp.copyTC(thread[i]->getTC());
1048        temp.unserialize(cp, csprintf("%s.xc.%i", section, i));
1049        thread[i]->getTC()->copyArchRegs(temp.getTC());
1050    }
1051}
1052
1053template <class Impl>
1054unsigned int
1055FullO3CPU<Impl>::drain(Event *drain_event)
1056{
1057    DPRINTF(O3CPU, "Switching out\n");
1058
1059    // If the CPU isn't doing anything, then return immediately.
1060    if (_status == Idle || _status == SwitchedOut) {
1061        return 0;
1062    }
1063
1064    drainCount = 0;
1065    fetch.drain();
1066    decode.drain();
1067    rename.drain();
1068    iew.drain();
1069    commit.drain();
1070
1071    // Wake the CPU and record activity so everything can drain out if
1072    // the CPU was not able to immediately drain.
1073    if (getState() != SimObject::Drained) {
1074        // A bit of a hack...set the drainEvent after all the drain()
1075        // calls have been made, that way if all of the stages drain
1076        // immediately, the signalDrained() function knows not to call
1077        // process on the drain event.
1078        drainEvent = drain_event;
1079
1080        wakeCPU();
1081        activityRec.activity();
1082
1083        return 1;
1084    } else {
1085        return 0;
1086    }
1087}
1088
1089template <class Impl>
1090void
1091FullO3CPU<Impl>::resume()
1092{
1093    fetch.resume();
1094    decode.resume();
1095    rename.resume();
1096    iew.resume();
1097    commit.resume();
1098
1099    changeState(SimObject::Running);
1100
1101    if (_status == SwitchedOut || _status == Idle)
1102        return;
1103
1104#if FULL_SYSTEM
1105    assert(system->getMemoryMode() == Enums::timing);
1106#endif
1107
1108    if (!tickEvent.scheduled())
1109        schedule(tickEvent, nextCycle());
1110    _status = Running;
1111}
1112
1113template <class Impl>
1114void
1115FullO3CPU<Impl>::signalDrained()
1116{
1117    if (++drainCount == NumStages) {
1118        if (tickEvent.scheduled())
1119            tickEvent.squash();
1120
1121        changeState(SimObject::Drained);
1122
1123        BaseCPU::switchOut();
1124
1125        if (drainEvent) {
1126            drainEvent->process();
1127            drainEvent = NULL;
1128        }
1129    }
1130    assert(drainCount <= 5);
1131}
1132
1133template <class Impl>
1134void
1135FullO3CPU<Impl>::switchOut()
1136{
1137    fetch.switchOut();
1138    rename.switchOut();
1139    iew.switchOut();
1140    commit.switchOut();
1141    instList.clear();
1142    while (!removeList.empty()) {
1143        removeList.pop();
1144    }
1145
1146    _status = SwitchedOut;
1147#if USE_CHECKER
1148    if (checker)
1149        checker->switchOut();
1150#endif
1151    if (tickEvent.scheduled())
1152        tickEvent.squash();
1153}
1154
1155template <class Impl>
1156void
1157FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
1158{
1159    // Flush out any old data from the time buffers.
1160    for (int i = 0; i < timeBuffer.getSize(); ++i) {
1161        timeBuffer.advance();
1162        fetchQueue.advance();
1163        decodeQueue.advance();
1164        renameQueue.advance();
1165        iewQueue.advance();
1166    }
1167
1168    activityRec.reset();
1169
1170    BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort());
1171
1172    fetch.takeOverFrom();
1173    decode.takeOverFrom();
1174    rename.takeOverFrom();
1175    iew.takeOverFrom();
1176    commit.takeOverFrom();
1177
1178    assert(!tickEvent.scheduled() || tickEvent.squashed());
1179
1180    // @todo: Figure out how to properly select the tid to put onto
1181    // the active threads list.
1182    ThreadID tid = 0;
1183
1184    list<ThreadID>::iterator isActive =
1185        std::find(activeThreads.begin(), activeThreads.end(), tid);
1186
1187    if (isActive == activeThreads.end()) {
1188        //May Need to Re-code this if the delay variable is the delay
1189        //needed for thread to activate
1190        DPRINTF(O3CPU, "Adding Thread %i to active threads list\n",
1191                tid);
1192
1193        activeThreads.push_back(tid);
1194    }
1195
1196    // Set all statuses to active, schedule the CPU's tick event.
1197    // @todo: Fix up statuses so this is handled properly
1198    ThreadID size = threadContexts.size();
1199    for (ThreadID i = 0; i < size; ++i) {
1200        ThreadContext *tc = threadContexts[i];
1201        if (tc->status() == ThreadContext::Active && _status != Running) {
1202            _status = Running;
1203            reschedule(tickEvent, nextCycle(), true);
1204        }
1205    }
1206    if (!tickEvent.scheduled())
1207        schedule(tickEvent, nextCycle());
1208}
1209
1210template <class Impl>
1211TheISA::MiscReg
1212FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid)
1213{
1214    return this->isa[tid].readMiscRegNoEffect(misc_reg);
1215}
1216
1217template <class Impl>
1218TheISA::MiscReg
1219FullO3CPU<Impl>::readMiscReg(int misc_reg, ThreadID tid)
1220{
1221    miscRegfileReads++;
1222    return this->isa[tid].readMiscReg(misc_reg, tcBase(tid));
1223}
1224
1225template <class Impl>
1226void
1227FullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg,
1228        const TheISA::MiscReg &val, ThreadID tid)
1229{
1230    this->isa[tid].setMiscRegNoEffect(misc_reg, val);
1231}
1232
1233template <class Impl>
1234void
1235FullO3CPU<Impl>::setMiscReg(int misc_reg,
1236        const TheISA::MiscReg &val, ThreadID tid)
1237{
1238    miscRegfileWrites++;
1239    this->isa[tid].setMiscReg(misc_reg, val, tcBase(tid));
1240}
1241
1242template <class Impl>
1243uint64_t
1244FullO3CPU<Impl>::readIntReg(int reg_idx)
1245{
1246    intRegfileReads++;
1247    return regFile.readIntReg(reg_idx);
1248}
1249
1250template <class Impl>
1251FloatReg
1252FullO3CPU<Impl>::readFloatReg(int reg_idx)
1253{
1254    fpRegfileReads++;
1255    return regFile.readFloatReg(reg_idx);
1256}
1257
1258template <class Impl>
1259FloatRegBits
1260FullO3CPU<Impl>::readFloatRegBits(int reg_idx)
1261{
1262    fpRegfileReads++;
1263    return regFile.readFloatRegBits(reg_idx);
1264}
1265
1266template <class Impl>
1267void
1268FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
1269{
1270    intRegfileWrites++;
1271    regFile.setIntReg(reg_idx, val);
1272}
1273
1274template <class Impl>
1275void
1276FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val)
1277{
1278    fpRegfileWrites++;
1279    regFile.setFloatReg(reg_idx, val);
1280}
1281
1282template <class Impl>
1283void
1284FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
1285{
1286    fpRegfileWrites++;
1287    regFile.setFloatRegBits(reg_idx, val);
1288}
1289
1290template <class Impl>
1291uint64_t
1292FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid)
1293{
1294    intRegfileReads++;
1295    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
1296
1297    return regFile.readIntReg(phys_reg);
1298}
1299
1300template <class Impl>
1301float
1302FullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid)
1303{
1304    fpRegfileReads++;
1305    int idx = reg_idx + TheISA::NumIntRegs;
1306    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1307
1308    return regFile.readFloatReg(phys_reg);
1309}
1310
1311template <class Impl>
1312uint64_t
1313FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid)
1314{
1315    fpRegfileReads++;
1316    int idx = reg_idx + TheISA::NumIntRegs;
1317    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1318
1319    return regFile.readFloatRegBits(phys_reg);
1320}
1321
1322template <class Impl>
1323void
1324FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid)
1325{
1326    intRegfileWrites++;
1327    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
1328
1329    regFile.setIntReg(phys_reg, val);
1330}
1331
1332template <class Impl>
1333void
1334FullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid)
1335{
1336    fpRegfileWrites++;
1337    int idx = reg_idx + TheISA::NumIntRegs;
1338    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1339
1340    regFile.setFloatReg(phys_reg, val);
1341}
1342
1343template <class Impl>
1344void
1345FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid)
1346{
1347    fpRegfileWrites++;
1348    int idx = reg_idx + TheISA::NumIntRegs;
1349    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1350
1351    regFile.setFloatRegBits(phys_reg, val);
1352}
1353
1354template <class Impl>
1355TheISA::PCState
1356FullO3CPU<Impl>::pcState(ThreadID tid)
1357{
1358    return commit.pcState(tid);
1359}
1360
1361template <class Impl>
1362void
1363FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid)
1364{
1365    commit.pcState(val, tid);
1366}
1367
1368template <class Impl>
1369Addr
1370FullO3CPU<Impl>::instAddr(ThreadID tid)
1371{
1372    return commit.instAddr(tid);
1373}
1374
1375template <class Impl>
1376Addr
1377FullO3CPU<Impl>::nextInstAddr(ThreadID tid)
1378{
1379    return commit.nextInstAddr(tid);
1380}
1381
1382template <class Impl>
1383MicroPC
1384FullO3CPU<Impl>::microPC(ThreadID tid)
1385{
1386    return commit.microPC(tid);
1387}
1388
1389template <class Impl>
1390void
1391FullO3CPU<Impl>::squashFromTC(ThreadID tid)
1392{
1393    this->thread[tid]->inSyscall = true;
1394    this->commit.generateTCEvent(tid);
1395}
1396
1397template <class Impl>
1398typename FullO3CPU<Impl>::ListIt
1399FullO3CPU<Impl>::addInst(DynInstPtr &inst)
1400{
1401    instList.push_back(inst);
1402
1403    return --(instList.end());
1404}
1405
1406template <class Impl>
1407void
1408FullO3CPU<Impl>::instDone(ThreadID tid)
1409{
1410    // Keep an instruction count.
1411    thread[tid]->numInst++;
1412    thread[tid]->numInsts++;
1413    committedInsts[tid]++;
1414    totalCommittedInsts++;
1415    system->totalNumInsts++;
1416    // Check for instruction-count-based events.
1417    comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
1418    system->instEventQueue.serviceEvents(system->totalNumInsts);
1419}
1420
1421template <class Impl>
1422void
1423FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst)
1424{
1425    removeInstsThisCycle = true;
1426
1427    removeList.push(inst->getInstListIt());
1428}
1429
1430template <class Impl>
1431void
1432FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
1433{
1434    DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s "
1435            "[sn:%lli]\n",
1436            inst->threadNumber, inst->pcState(), inst->seqNum);
1437
1438    removeInstsThisCycle = true;
1439
1440    // Remove the front instruction.
1441    removeList.push(inst->getInstListIt());
1442}
1443
1444template <class Impl>
1445void
1446FullO3CPU<Impl>::removeInstsNotInROB(ThreadID tid)
1447{
1448    DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction"
1449            " list.\n", tid);
1450
1451    ListIt end_it;
1452
1453    bool rob_empty = false;
1454
1455    if (instList.empty()) {
1456        return;
1457    } else if (rob.isEmpty(/*tid*/)) {
1458        DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n");
1459        end_it = instList.begin();
1460        rob_empty = true;
1461    } else {
1462        end_it = (rob.readTailInst(tid))->getInstListIt();
1463        DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n");
1464    }
1465
1466    removeInstsThisCycle = true;
1467
1468    ListIt inst_it = instList.end();
1469
1470    inst_it--;
1471
1472    // Walk through the instruction list, removing any instructions
1473    // that were inserted after the given instruction iterator, end_it.
1474    while (inst_it != end_it) {
1475        assert(!instList.empty());
1476
1477        squashInstIt(inst_it, tid);
1478
1479        inst_it--;
1480    }
1481
1482    // If the ROB was empty, then we actually need to remove the first
1483    // instruction as well.
1484    if (rob_empty) {
1485        squashInstIt(inst_it, tid);
1486    }
1487}
1488
1489template <class Impl>
1490void
1491FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid)
1492{
1493    assert(!instList.empty());
1494
1495    removeInstsThisCycle = true;
1496
1497    ListIt inst_iter = instList.end();
1498
1499    inst_iter--;
1500
1501    DPRINTF(O3CPU, "Deleting instructions from instruction "
1502            "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1503            tid, seq_num, (*inst_iter)->seqNum);
1504
1505    while ((*inst_iter)->seqNum > seq_num) {
1506
1507        bool break_loop = (inst_iter == instList.begin());
1508
1509        squashInstIt(inst_iter, tid);
1510
1511        inst_iter--;
1512
1513        if (break_loop)
1514            break;
1515    }
1516}
1517
1518template <class Impl>
1519inline void
1520FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid)
1521{
1522    if ((*instIt)->threadNumber == tid) {
1523        DPRINTF(O3CPU, "Squashing instruction, "
1524                "[tid:%i] [sn:%lli] PC %s\n",
1525                (*instIt)->threadNumber,
1526                (*instIt)->seqNum,
1527                (*instIt)->pcState());
1528
1529        // Mark it as squashed.
1530        (*instIt)->setSquashed();
1531
1532        // @todo: Formulate a consistent method for deleting
1533        // instructions from the instruction list
1534        // Remove the instruction from the list.
1535        removeList.push(instIt);
1536    }
1537}
1538
1539template <class Impl>
1540void
1541FullO3CPU<Impl>::cleanUpRemovedInsts()
1542{
1543    while (!removeList.empty()) {
1544        DPRINTF(O3CPU, "Removing instruction, "
1545                "[tid:%i] [sn:%lli] PC %s\n",
1546                (*removeList.front())->threadNumber,
1547                (*removeList.front())->seqNum,
1548                (*removeList.front())->pcState());
1549
1550        instList.erase(removeList.front());
1551
1552        removeList.pop();
1553    }
1554
1555    removeInstsThisCycle = false;
1556}
1557/*
1558template <class Impl>
1559void
1560FullO3CPU<Impl>::removeAllInsts()
1561{
1562    instList.clear();
1563}
1564*/
1565template <class Impl>
1566void
1567FullO3CPU<Impl>::dumpInsts()
1568{
1569    int num = 0;
1570
1571    ListIt inst_list_it = instList.begin();
1572
1573    cprintf("Dumping Instruction List\n");
1574
1575    while (inst_list_it != instList.end()) {
1576        cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1577                "Squashed:%i\n\n",
1578                num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber,
1579                (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
1580                (*inst_list_it)->isSquashed());
1581        inst_list_it++;
1582        ++num;
1583    }
1584}
1585/*
1586template <class Impl>
1587void
1588FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
1589{
1590    iew.wakeDependents(inst);
1591}
1592*/
1593template <class Impl>
1594void
1595FullO3CPU<Impl>::wakeCPU()
1596{
1597    if (activityRec.active() || tickEvent.scheduled()) {
1598        DPRINTF(Activity, "CPU already running.\n");
1599        return;
1600    }
1601
1602    DPRINTF(Activity, "Waking up CPU\n");
1603
1604    idleCycles += tickToCycles((curTick() - 1) - lastRunningCycle);
1605    numCycles += tickToCycles((curTick() - 1) - lastRunningCycle);
1606
1607    schedule(tickEvent, nextCycle());
1608}
1609
1610#if FULL_SYSTEM
1611template <class Impl>
1612void
1613FullO3CPU<Impl>::wakeup()
1614{
1615    if (this->thread[0]->status() != ThreadContext::Suspended)
1616        return;
1617
1618    this->wakeCPU();
1619
1620    DPRINTF(Quiesce, "Suspended Processor woken\n");
1621    this->threadContexts[0]->activate();
1622}
1623#endif
1624
1625template <class Impl>
1626ThreadID
1627FullO3CPU<Impl>::getFreeTid()
1628{
1629    for (ThreadID tid = 0; tid < numThreads; tid++) {
1630        if (!tids[tid]) {
1631            tids[tid] = true;
1632            return tid;
1633        }
1634    }
1635
1636    return InvalidThreadID;
1637}
1638
1639template <class Impl>
1640void
1641FullO3CPU<Impl>::doContextSwitch()
1642{
1643    if (contextSwitch) {
1644
1645        //ADD CODE TO DEACTIVE THREAD HERE (???)
1646
1647        ThreadID size = cpuWaitList.size();
1648        for (ThreadID tid = 0; tid < size; tid++) {
1649            activateWhenReady(tid);
1650        }
1651
1652        if (cpuWaitList.size() == 0)
1653            contextSwitch = true;
1654    }
1655}
1656
1657template <class Impl>
1658void
1659FullO3CPU<Impl>::updateThreadPriority()
1660{
1661    if (activeThreads.size() > 1) {
1662        //DEFAULT TO ROUND ROBIN SCHEME
1663        //e.g. Move highest priority to end of thread list
1664        list<ThreadID>::iterator list_begin = activeThreads.begin();
1665        list<ThreadID>::iterator list_end   = activeThreads.end();
1666
1667        unsigned high_thread = *list_begin;
1668
1669        activeThreads.erase(list_begin);
1670
1671        activeThreads.push_back(high_thread);
1672    }
1673}
1674
1675// Forward declaration of FullO3CPU.
1676template class FullO3CPU<O3CPUImpl>;
1677