cpu.cc revision 2680:246e7104f744
1/*
2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Kevin Lim
29 */
30
31#include "config/full_system.hh"
32
33#if FULL_SYSTEM
34#include "sim/system.hh"
35#else
36#include "sim/process.hh"
37#endif
38
39#include "cpu/activity.hh"
40#include "cpu/checker/cpu.hh"
41#include "cpu/cpu_exec_context.hh"
42#include "cpu/thread_context.hh"
43#include "cpu/o3/alpha_dyn_inst.hh"
44#include "cpu/o3/alpha_impl.hh"
45#include "cpu/o3/cpu.hh"
46
47#include "sim/root.hh"
48#include "sim/stat_control.hh"
49
50using namespace std;
51using namespace TheISA;
52
53BaseFullCPU::BaseFullCPU(Params *params)
54    : BaseCPU(params), cpu_id(0)
55{
56}
57
58void
59BaseFullCPU::regStats()
60{
61    BaseCPU::regStats();
62}
63
64template <class Impl>
65FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
66    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
67{
68}
69
70template <class Impl>
71void
72FullO3CPU<Impl>::TickEvent::process()
73{
74    cpu->tick();
75}
76
77template <class Impl>
78const char *
79FullO3CPU<Impl>::TickEvent::description()
80{
81    return "FullO3CPU tick event";
82}
83
84template <class Impl>
85FullO3CPU<Impl>::FullO3CPU(Params *params)
86    : BaseFullCPU(params),
87      tickEvent(this),
88      removeInstsThisCycle(false),
89      fetch(params),
90      decode(params),
91      rename(params),
92      iew(params),
93      commit(params),
94
95      regFile(params->numPhysIntRegs, params->numPhysFloatRegs),
96
97      freeList(params->numberOfThreads,//number of activeThreads
98               TheISA::NumIntRegs, params->numPhysIntRegs,
99               TheISA::NumFloatRegs, params->numPhysFloatRegs),
100
101      rob(params->numROBEntries, params->squashWidth,
102          params->smtROBPolicy, params->smtROBThreshold,
103          params->numberOfThreads),
104
105      scoreboard(params->numberOfThreads,//number of activeThreads
106                 TheISA::NumIntRegs, params->numPhysIntRegs,
107                 TheISA::NumFloatRegs, params->numPhysFloatRegs,
108                 TheISA::NumMiscRegs * number_of_threads,
109                 TheISA::ZeroReg),
110
111      // For now just have these time buffers be pretty big.
112      // @todo: Make these time buffer sizes parameters or derived
113      // from latencies
114      timeBuffer(5, 5),
115      fetchQueue(5, 5),
116      decodeQueue(5, 5),
117      renameQueue(5, 5),
118      iewQueue(5, 5),
119      activityRec(NumStages, 10, params->activity),
120
121      globalSeqNum(1),
122
123#if FULL_SYSTEM
124      system(params->system),
125      memCtrl(system->memctrl),
126      physmem(system->physmem),
127#endif // FULL_SYSTEM
128      mem(params->mem),
129      switchCount(0),
130      deferRegistration(params->deferRegistration),
131      numThreads(number_of_threads)
132{
133    _status = Idle;
134
135    if (params->checker) {
136        BaseCPU *temp_checker = params->checker;
137        checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
138        checker->setMemory(mem);
139#if FULL_SYSTEM
140        checker->setSystem(params->system);
141#endif
142    } else {
143        checker = NULL;
144    }
145
146#if !FULL_SYSTEM
147    thread.resize(number_of_threads);
148    tids.resize(number_of_threads);
149#endif
150
151    // The stages also need their CPU pointer setup.  However this
152    // must be done at the upper level CPU because they have pointers
153    // to the upper level CPU, and not this FullO3CPU.
154
155    // Set up Pointers to the activeThreads list for each stage
156    fetch.setActiveThreads(&activeThreads);
157    decode.setActiveThreads(&activeThreads);
158    rename.setActiveThreads(&activeThreads);
159    iew.setActiveThreads(&activeThreads);
160    commit.setActiveThreads(&activeThreads);
161
162    // Give each of the stages the time buffer they will use.
163    fetch.setTimeBuffer(&timeBuffer);
164    decode.setTimeBuffer(&timeBuffer);
165    rename.setTimeBuffer(&timeBuffer);
166    iew.setTimeBuffer(&timeBuffer);
167    commit.setTimeBuffer(&timeBuffer);
168
169    // Also setup each of the stages' queues.
170    fetch.setFetchQueue(&fetchQueue);
171    decode.setFetchQueue(&fetchQueue);
172    commit.setFetchQueue(&fetchQueue);
173    decode.setDecodeQueue(&decodeQueue);
174    rename.setDecodeQueue(&decodeQueue);
175    rename.setRenameQueue(&renameQueue);
176    iew.setRenameQueue(&renameQueue);
177    iew.setIEWQueue(&iewQueue);
178    commit.setIEWQueue(&iewQueue);
179    commit.setRenameQueue(&renameQueue);
180
181    commit.setFetchStage(&fetch);
182    commit.setIEWStage(&iew);
183    rename.setIEWStage(&iew);
184    rename.setCommitStage(&commit);
185
186#if !FULL_SYSTEM
187    int active_threads = params->workload.size();
188#else
189    int active_threads = 1;
190#endif
191
192    //Make Sure That this a Valid Architeture
193    assert(params->numPhysIntRegs   >= numThreads * TheISA::NumIntRegs);
194    assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
195
196    rename.setScoreboard(&scoreboard);
197    iew.setScoreboard(&scoreboard);
198
199    // Setup the rename map for whichever stages need it.
200    PhysRegIndex lreg_idx = 0;
201    PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs
202
203    for (int tid=0; tid < numThreads; tid++) {
204        bool bindRegs = (tid <= active_threads - 1);
205
206        commitRenameMap[tid].init(TheISA::NumIntRegs,
207                                  params->numPhysIntRegs,
208                                  lreg_idx,            //Index for Logical. Regs
209
210                                  TheISA::NumFloatRegs,
211                                  params->numPhysFloatRegs,
212                                  freg_idx,            //Index for Float Regs
213
214                                  TheISA::NumMiscRegs,
215
216                                  TheISA::ZeroReg,
217                                  TheISA::ZeroReg,
218
219                                  tid,
220                                  false);
221
222        renameMap[tid].init(TheISA::NumIntRegs,
223                            params->numPhysIntRegs,
224                            lreg_idx,                  //Index for Logical. Regs
225
226                            TheISA::NumFloatRegs,
227                            params->numPhysFloatRegs,
228                            freg_idx,                  //Index for Float Regs
229
230                            TheISA::NumMiscRegs,
231
232                            TheISA::ZeroReg,
233                            TheISA::ZeroReg,
234
235                            tid,
236                            bindRegs);
237    }
238
239    rename.setRenameMap(renameMap);
240    commit.setRenameMap(commitRenameMap);
241
242    // Give renameMap & rename stage access to the freeList;
243    for (int i=0; i < numThreads; i++) {
244        renameMap[i].setFreeList(&freeList);
245    }
246    rename.setFreeList(&freeList);
247
248    // Setup the page table for whichever stages need it.
249#if !FULL_SYSTEM
250//    fetch.setPageTable(pTable);
251//    iew.setPageTable(pTable);
252#endif
253
254    // Setup the ROB for whichever stages need it.
255    commit.setROB(&rob);
256
257    lastRunningCycle = curTick;
258
259    contextSwitch = false;
260}
261
262template <class Impl>
263FullO3CPU<Impl>::~FullO3CPU()
264{
265}
266
267template <class Impl>
268void
269FullO3CPU<Impl>::fullCPURegStats()
270{
271    BaseFullCPU::regStats();
272
273    // Register any of the FullCPU's stats here.
274    timesIdled
275        .name(name() + ".timesIdled")
276        .desc("Number of times that the entire CPU went into an idle state and"
277              " unscheduled itself")
278        .prereq(timesIdled);
279
280    idleCycles
281        .name(name() + ".idleCycles")
282        .desc("Total number of cycles that the CPU has spent unscheduled due "
283              "to idling")
284        .prereq(idleCycles);
285
286    // Number of Instructions simulated
287    // --------------------------------
288    // Should probably be in Base CPU but need templated
289    // MaxThreads so put in here instead
290    committedInsts
291        .init(numThreads)
292        .name(name() + ".committedInsts")
293        .desc("Number of Instructions Simulated");
294
295    totalCommittedInsts
296        .name(name() + ".committedInsts_total")
297        .desc("Number of Instructions Simulated");
298
299    cpi
300        .name(name() + ".cpi")
301        .desc("CPI: Cycles Per Instruction")
302        .precision(6);
303    cpi = simTicks / committedInsts;
304
305    totalCpi
306        .name(name() + ".cpi_total")
307        .desc("CPI: Total CPI of All Threads")
308        .precision(6);
309    totalCpi = simTicks / totalCommittedInsts;
310
311    ipc
312        .name(name() + ".ipc")
313        .desc("IPC: Instructions Per Cycle")
314        .precision(6);
315    ipc =  committedInsts / simTicks;
316
317    totalIpc
318        .name(name() + ".ipc_total")
319        .desc("IPC: Total IPC of All Threads")
320        .precision(6);
321    totalIpc =  totalCommittedInsts / simTicks;
322
323}
324
325template <class Impl>
326void
327FullO3CPU<Impl>::tick()
328{
329    DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
330
331    ++numCycles;
332
333//    activity = false;
334
335    //Tick each of the stages
336    fetch.tick();
337
338    decode.tick();
339
340    rename.tick();
341
342    iew.tick();
343
344    commit.tick();
345
346#if !FULL_SYSTEM
347    doContextSwitch();
348#endif
349
350    // Now advance the time buffers
351    timeBuffer.advance();
352
353    fetchQueue.advance();
354    decodeQueue.advance();
355    renameQueue.advance();
356    iewQueue.advance();
357
358    activityRec.advance();
359
360    if (removeInstsThisCycle) {
361        cleanUpRemovedInsts();
362    }
363
364    if (!tickEvent.scheduled()) {
365        if (_status == SwitchedOut) {
366            // increment stat
367            lastRunningCycle = curTick;
368        } else if (!activityRec.active()) {
369            lastRunningCycle = curTick;
370            timesIdled++;
371        } else {
372            tickEvent.schedule(curTick + cycles(1));
373        }
374    }
375
376#if !FULL_SYSTEM
377    updateThreadPriority();
378#endif
379
380}
381
382template <class Impl>
383void
384FullO3CPU<Impl>::init()
385{
386    if (!deferRegistration) {
387        registerThreadContexts();
388    }
389
390    // Set inSyscall so that the CPU doesn't squash when initially
391    // setting up registers.
392    for (int i = 0; i < number_of_threads; ++i)
393        thread[i]->inSyscall = true;
394
395    for (int tid=0; tid < number_of_threads; tid++) {
396#if FULL_SYSTEM
397        ThreadContext *src_tc = threadContexts[tid];
398#else
399        ThreadContext *src_tc = thread[tid]->getTC();
400#endif
401        // Threads start in the Suspended State
402        if (src_tc->status() != ThreadContext::Suspended) {
403            continue;
404        }
405
406#if FULL_SYSTEM
407        TheISA::initCPU(src_tc, src_tc->readCpuId());
408#endif
409    }
410
411    // Clear inSyscall.
412    for (int i = 0; i < number_of_threads; ++i)
413        thread[i]->inSyscall = false;
414
415    // Initialize stages.
416    fetch.initStage();
417    iew.initStage();
418    rename.initStage();
419    commit.initStage();
420
421    commit.setThreads(thread);
422}
423
424template <class Impl>
425void
426FullO3CPU<Impl>::insertThread(unsigned tid)
427{
428    DPRINTF(FullCPU,"[tid:%i] Initializing thread data");
429    // Will change now that the PC and thread state is internal to the CPU
430    // and not in the CPUExecContext.
431#if 0
432#if FULL_SYSTEM
433    ThreadContext *src_tc = system->threadContexts[tid];
434#else
435    CPUExecContext *src_tc = thread[tid];
436#endif
437
438    //Bind Int Regs to Rename Map
439    for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
440        PhysRegIndex phys_reg = freeList.getIntReg();
441
442        renameMap[tid].setEntry(ireg,phys_reg);
443        scoreboard.setReg(phys_reg);
444    }
445
446    //Bind Float Regs to Rename Map
447    for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
448        PhysRegIndex phys_reg = freeList.getFloatReg();
449
450        renameMap[tid].setEntry(freg,phys_reg);
451        scoreboard.setReg(phys_reg);
452    }
453
454    //Copy Thread Data Into RegFile
455    this->copyFromTC(tid);
456
457    //Set PC/NPC
458    regFile.pc[tid]  = src_tc->readPC();
459    regFile.npc[tid] = src_tc->readNextPC();
460
461    src_tc->setStatus(ThreadContext::Active);
462
463    activateContext(tid,1);
464
465    //Reset ROB/IQ/LSQ Entries
466    commit.rob->resetEntries();
467    iew.resetEntries();
468#endif
469}
470
471template <class Impl>
472void
473FullO3CPU<Impl>::removeThread(unsigned tid)
474{
475    DPRINTF(FullCPU,"[tid:%i] Removing thread data");
476#if 0
477    //Unbind Int Regs from Rename Map
478    for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
479        PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
480
481        scoreboard.unsetReg(phys_reg);
482        freeList.addReg(phys_reg);
483    }
484
485    //Unbind Float Regs from Rename Map
486    for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
487        PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
488
489        scoreboard.unsetReg(phys_reg);
490        freeList.addReg(phys_reg);
491    }
492
493    //Copy Thread Data From RegFile
494    /* Fix Me:
495     * Do we really need to do this if we are removing a thread
496     * in the sense that it's finished (exiting)? If the thread is just
497     * being suspended we might...
498     */
499//    this->copyToTC(tid);
500
501    //Squash Throughout Pipeline
502    fetch.squash(0,tid);
503    decode.squash(tid);
504    rename.squash(tid);
505
506    assert(iew.ldstQueue.getCount(tid) == 0);
507
508    //Reset ROB/IQ/LSQ Entries
509    if (activeThreads.size() >= 1) {
510        commit.rob->resetEntries();
511        iew.resetEntries();
512    }
513#endif
514}
515
516
517template <class Impl>
518void
519FullO3CPU<Impl>::activateWhenReady(int tid)
520{
521    DPRINTF(FullCPU,"[tid:%i]: Checking if resources are available for incoming"
522            "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
523            tid);
524
525    bool ready = true;
526
527    if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
528        DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
529                "Phys. Int. Regs.\n",
530                tid);
531        ready = false;
532    } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
533        DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
534                "Phys. Float. Regs.\n",
535                tid);
536        ready = false;
537    } else if (commit.rob->numFreeEntries() >=
538               commit.rob->entryAmount(activeThreads.size() + 1)) {
539        DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
540                "ROB entries.\n",
541                tid);
542        ready = false;
543    } else if (iew.instQueue.numFreeEntries() >=
544               iew.instQueue.entryAmount(activeThreads.size() + 1)) {
545        DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
546                "IQ entries.\n",
547                tid);
548        ready = false;
549    } else if (iew.ldstQueue.numFreeEntries() >=
550               iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
551        DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
552                "LSQ entries.\n",
553                tid);
554        ready = false;
555    }
556
557    if (ready) {
558        insertThread(tid);
559
560        contextSwitch = false;
561
562        cpuWaitList.remove(tid);
563    } else {
564        suspendContext(tid);
565
566        //blocks fetch
567        contextSwitch = true;
568
569        //do waitlist
570        cpuWaitList.push_back(tid);
571    }
572}
573
574template <class Impl>
575void
576FullO3CPU<Impl>::activateContext(int tid, int delay)
577{
578    // Needs to set each stage to running as well.
579    list<unsigned>::iterator isActive = find(
580        activeThreads.begin(), activeThreads.end(), tid);
581
582    if (isActive == activeThreads.end()) {
583        //May Need to Re-code this if the delay variable is the
584        //delay needed for thread to activate
585        DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
586                tid);
587
588        activeThreads.push_back(tid);
589    }
590
591    assert(_status == Idle || _status == SwitchedOut);
592
593    scheduleTickEvent(delay);
594
595    // Be sure to signal that there's some activity so the CPU doesn't
596    // deschedule itself.
597    activityRec.activity();
598    fetch.wakeFromQuiesce();
599
600    _status = Running;
601}
602
603template <class Impl>
604void
605FullO3CPU<Impl>::suspendContext(int tid)
606{
607    DPRINTF(FullCPU,"[tid: %i]: Suspended ...\n", tid);
608    unscheduleTickEvent();
609    _status = Idle;
610/*
611    //Remove From Active List, if Active
612    list<unsigned>::iterator isActive = find(
613        activeThreads.begin(), activeThreads.end(), tid);
614
615    if (isActive != activeThreads.end()) {
616        DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
617                tid);
618        activeThreads.erase(isActive);
619    }
620*/
621}
622
623template <class Impl>
624void
625FullO3CPU<Impl>::deallocateContext(int tid)
626{
627    DPRINTF(FullCPU,"[tid:%i]: Deallocating ...", tid);
628/*
629    //Remove From Active List, if Active
630    list<unsigned>::iterator isActive = find(
631        activeThreads.begin(), activeThreads.end(), tid);
632
633    if (isActive != activeThreads.end()) {
634        DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
635                tid);
636        activeThreads.erase(isActive);
637
638        removeThread(tid);
639    }
640*/
641}
642
643template <class Impl>
644void
645FullO3CPU<Impl>::haltContext(int tid)
646{
647    DPRINTF(FullCPU,"[tid:%i]: Halted ...", tid);
648/*
649    //Remove From Active List, if Active
650    list<unsigned>::iterator isActive = find(
651        activeThreads.begin(), activeThreads.end(), tid);
652
653    if (isActive != activeThreads.end()) {
654        DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
655                tid);
656        activeThreads.erase(isActive);
657
658        removeThread(tid);
659    }
660*/
661}
662
663template <class Impl>
664void
665FullO3CPU<Impl>::switchOut(Sampler *_sampler)
666{
667    sampler = _sampler;
668    switchCount = 0;
669    fetch.switchOut();
670    decode.switchOut();
671    rename.switchOut();
672    iew.switchOut();
673    commit.switchOut();
674
675    // Wake the CPU and record activity so everything can drain out if
676    // the CPU is currently idle.
677    wakeCPU();
678    activityRec.activity();
679}
680
681template <class Impl>
682void
683FullO3CPU<Impl>::signalSwitched()
684{
685    if (++switchCount == NumStages) {
686        fetch.doSwitchOut();
687        rename.doSwitchOut();
688        commit.doSwitchOut();
689        instList.clear();
690        while (!removeList.empty()) {
691            removeList.pop();
692        }
693
694        if (checker)
695            checker->switchOut(sampler);
696
697        if (tickEvent.scheduled())
698            tickEvent.squash();
699        sampler->signalSwitched();
700        _status = SwitchedOut;
701    }
702    assert(switchCount <= 5);
703}
704
705template <class Impl>
706void
707FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
708{
709    // Flush out any old data from the time buffers.
710    for (int i = 0; i < 10; ++i) {
711        timeBuffer.advance();
712        fetchQueue.advance();
713        decodeQueue.advance();
714        renameQueue.advance();
715        iewQueue.advance();
716    }
717
718    activityRec.reset();
719
720    BaseCPU::takeOverFrom(oldCPU);
721
722    fetch.takeOverFrom();
723    decode.takeOverFrom();
724    rename.takeOverFrom();
725    iew.takeOverFrom();
726    commit.takeOverFrom();
727
728    assert(!tickEvent.scheduled());
729
730    // @todo: Figure out how to properly select the tid to put onto
731    // the active threads list.
732    int tid = 0;
733
734    list<unsigned>::iterator isActive = find(
735        activeThreads.begin(), activeThreads.end(), tid);
736
737    if (isActive == activeThreads.end()) {
738        //May Need to Re-code this if the delay variable is the delay
739        //needed for thread to activate
740        DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
741                tid);
742
743        activeThreads.push_back(tid);
744    }
745
746    // Set all statuses to active, schedule the CPU's tick event.
747    // @todo: Fix up statuses so this is handled properly
748    for (int i = 0; i < threadContexts.size(); ++i) {
749        ThreadContext *tc = threadContexts[i];
750        if (tc->status() == ThreadContext::Active && _status != Running) {
751            _status = Running;
752            tickEvent.schedule(curTick);
753        }
754    }
755    if (!tickEvent.scheduled())
756        tickEvent.schedule(curTick);
757}
758
759template <class Impl>
760uint64_t
761FullO3CPU<Impl>::readIntReg(int reg_idx)
762{
763    return regFile.readIntReg(reg_idx);
764}
765
766template <class Impl>
767FloatReg
768FullO3CPU<Impl>::readFloatReg(int reg_idx, int width)
769{
770    return regFile.readFloatReg(reg_idx, width);
771}
772
773template <class Impl>
774FloatReg
775FullO3CPU<Impl>::readFloatReg(int reg_idx)
776{
777    return regFile.readFloatReg(reg_idx);
778}
779
780template <class Impl>
781FloatRegBits
782FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width)
783{
784    return regFile.readFloatRegBits(reg_idx, width);
785}
786
787template <class Impl>
788FloatRegBits
789FullO3CPU<Impl>::readFloatRegBits(int reg_idx)
790{
791    return regFile.readFloatRegBits(reg_idx);
792}
793
794template <class Impl>
795void
796FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
797{
798    regFile.setIntReg(reg_idx, val);
799}
800
801template <class Impl>
802void
803FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width)
804{
805    regFile.setFloatReg(reg_idx, val, width);
806}
807
808template <class Impl>
809void
810FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val)
811{
812    regFile.setFloatReg(reg_idx, val);
813}
814
815template <class Impl>
816void
817FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width)
818{
819    regFile.setFloatRegBits(reg_idx, val, width);
820}
821
822template <class Impl>
823void
824FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
825{
826    regFile.setFloatRegBits(reg_idx, val);
827}
828
829template <class Impl>
830uint64_t
831FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid)
832{
833    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
834
835    return regFile.readIntReg(phys_reg);
836}
837
838template <class Impl>
839float
840FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid)
841{
842    int idx = reg_idx + TheISA::FP_Base_DepTag;
843    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
844
845    return regFile.readFloatReg(phys_reg);
846}
847
848template <class Impl>
849double
850FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid)
851{
852    int idx = reg_idx + TheISA::FP_Base_DepTag;
853    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
854
855    return regFile.readFloatReg(phys_reg, 64);
856}
857
858template <class Impl>
859uint64_t
860FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid)
861{
862    int idx = reg_idx + TheISA::FP_Base_DepTag;
863    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
864
865    return regFile.readFloatRegBits(phys_reg);
866}
867
868template <class Impl>
869void
870FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid)
871{
872    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
873
874    regFile.setIntReg(phys_reg, val);
875}
876
877template <class Impl>
878void
879FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid)
880{
881    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
882
883    regFile.setFloatReg(phys_reg, val);
884}
885
886template <class Impl>
887void
888FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid)
889{
890    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
891
892    regFile.setFloatReg(phys_reg, val, 64);
893}
894
895template <class Impl>
896void
897FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid)
898{
899    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
900
901    regFile.setFloatRegBits(phys_reg, val);
902}
903
904template <class Impl>
905uint64_t
906FullO3CPU<Impl>::readPC(unsigned tid)
907{
908    return commit.readPC(tid);
909}
910
911template <class Impl>
912void
913FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid)
914{
915    commit.setPC(new_PC, tid);
916}
917
918template <class Impl>
919uint64_t
920FullO3CPU<Impl>::readNextPC(unsigned tid)
921{
922    return commit.readNextPC(tid);
923}
924
925template <class Impl>
926void
927FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid)
928{
929    commit.setNextPC(val, tid);
930}
931
932template <class Impl>
933typename FullO3CPU<Impl>::ListIt
934FullO3CPU<Impl>::addInst(DynInstPtr &inst)
935{
936    instList.push_back(inst);
937
938    return --(instList.end());
939}
940
941template <class Impl>
942void
943FullO3CPU<Impl>::instDone(unsigned tid)
944{
945    // Keep an instruction count.
946    thread[tid]->numInst++;
947    thread[tid]->numInsts++;
948    committedInsts[tid]++;
949    totalCommittedInsts++;
950
951    // Check for instruction-count-based events.
952    comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
953}
954
955template <class Impl>
956void
957FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst)
958{
959    removeInstsThisCycle = true;
960
961    removeList.push(inst->getInstListIt());
962}
963
964template <class Impl>
965void
966FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
967{
968    DPRINTF(FullCPU, "FullCPU: Removing committed instruction [tid:%i] PC %#x "
969            "[sn:%lli]\n",
970            inst->threadNumber, inst->readPC(), inst->seqNum);
971
972    removeInstsThisCycle = true;
973
974    // Remove the front instruction.
975    removeList.push(inst->getInstListIt());
976}
977
978template <class Impl>
979void
980FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
981{
982    DPRINTF(FullCPU, "FullCPU: Thread %i: Deleting instructions from instruction"
983            " list.\n", tid);
984
985    ListIt end_it;
986
987    bool rob_empty = false;
988
989    if (instList.empty()) {
990        return;
991    } else if (rob.isEmpty(/*tid*/)) {
992        DPRINTF(FullCPU, "FullCPU: ROB is empty, squashing all insts.\n");
993        end_it = instList.begin();
994        rob_empty = true;
995    } else {
996        end_it = (rob.readTailInst(tid))->getInstListIt();
997        DPRINTF(FullCPU, "FullCPU: ROB is not empty, squashing insts not in ROB.\n");
998    }
999
1000    removeInstsThisCycle = true;
1001
1002    ListIt inst_it = instList.end();
1003
1004    inst_it--;
1005
1006    // Walk through the instruction list, removing any instructions
1007    // that were inserted after the given instruction iterator, end_it.
1008    while (inst_it != end_it) {
1009        assert(!instList.empty());
1010
1011        squashInstIt(inst_it, tid);
1012
1013        inst_it--;
1014    }
1015
1016    // If the ROB was empty, then we actually need to remove the first
1017    // instruction as well.
1018    if (rob_empty) {
1019        squashInstIt(inst_it, tid);
1020    }
1021}
1022
1023template <class Impl>
1024void
1025FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num,
1026                                  unsigned tid)
1027{
1028    assert(!instList.empty());
1029
1030    removeInstsThisCycle = true;
1031
1032    ListIt inst_iter = instList.end();
1033
1034    inst_iter--;
1035
1036    DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
1037            "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1038            tid, seq_num, (*inst_iter)->seqNum);
1039
1040    while ((*inst_iter)->seqNum > seq_num) {
1041
1042        bool break_loop = (inst_iter == instList.begin());
1043
1044        squashInstIt(inst_iter, tid);
1045
1046        inst_iter--;
1047
1048        if (break_loop)
1049            break;
1050    }
1051}
1052
1053template <class Impl>
1054inline void
1055FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid)
1056{
1057    if ((*instIt)->threadNumber == tid) {
1058        DPRINTF(FullCPU, "FullCPU: Squashing instruction, "
1059                "[tid:%i] [sn:%lli] PC %#x\n",
1060                (*instIt)->threadNumber,
1061                (*instIt)->seqNum,
1062                (*instIt)->readPC());
1063
1064        // Mark it as squashed.
1065        (*instIt)->setSquashed();
1066
1067        // @todo: Formulate a consistent method for deleting
1068        // instructions from the instruction list
1069        // Remove the instruction from the list.
1070        removeList.push(instIt);
1071    }
1072}
1073
1074template <class Impl>
1075void
1076FullO3CPU<Impl>::cleanUpRemovedInsts()
1077{
1078    while (!removeList.empty()) {
1079        DPRINTF(FullCPU, "FullCPU: Removing instruction, "
1080                "[tid:%i] [sn:%lli] PC %#x\n",
1081                (*removeList.front())->threadNumber,
1082                (*removeList.front())->seqNum,
1083                (*removeList.front())->readPC());
1084
1085        instList.erase(removeList.front());
1086
1087        removeList.pop();
1088    }
1089
1090    removeInstsThisCycle = false;
1091}
1092/*
1093template <class Impl>
1094void
1095FullO3CPU<Impl>::removeAllInsts()
1096{
1097    instList.clear();
1098}
1099*/
1100template <class Impl>
1101void
1102FullO3CPU<Impl>::dumpInsts()
1103{
1104    int num = 0;
1105
1106    ListIt inst_list_it = instList.begin();
1107
1108    cprintf("Dumping Instruction List\n");
1109
1110    while (inst_list_it != instList.end()) {
1111        cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1112                "Squashed:%i\n\n",
1113                num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
1114                (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
1115                (*inst_list_it)->isSquashed());
1116        inst_list_it++;
1117        ++num;
1118    }
1119}
1120/*
1121template <class Impl>
1122void
1123FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
1124{
1125    iew.wakeDependents(inst);
1126}
1127*/
1128template <class Impl>
1129void
1130FullO3CPU<Impl>::wakeCPU()
1131{
1132    if (activityRec.active() || tickEvent.scheduled()) {
1133        DPRINTF(Activity, "CPU already running.\n");
1134        return;
1135    }
1136
1137    DPRINTF(Activity, "Waking up CPU\n");
1138
1139    idleCycles += (curTick - 1) - lastRunningCycle;
1140
1141    tickEvent.schedule(curTick);
1142}
1143
1144template <class Impl>
1145int
1146FullO3CPU<Impl>::getFreeTid()
1147{
1148    for (int i=0; i < numThreads; i++) {
1149        if (!tids[i]) {
1150            tids[i] = true;
1151            return i;
1152        }
1153    }
1154
1155    return -1;
1156}
1157
1158template <class Impl>
1159void
1160FullO3CPU<Impl>::doContextSwitch()
1161{
1162    if (contextSwitch) {
1163
1164        //ADD CODE TO DEACTIVE THREAD HERE (???)
1165
1166        for (int tid=0; tid < cpuWaitList.size(); tid++) {
1167            activateWhenReady(tid);
1168        }
1169
1170        if (cpuWaitList.size() == 0)
1171            contextSwitch = true;
1172    }
1173}
1174
1175template <class Impl>
1176void
1177FullO3CPU<Impl>::updateThreadPriority()
1178{
1179    if (activeThreads.size() > 1)
1180    {
1181        //DEFAULT TO ROUND ROBIN SCHEME
1182        //e.g. Move highest priority to end of thread list
1183        list<unsigned>::iterator list_begin = activeThreads.begin();
1184        list<unsigned>::iterator list_end   = activeThreads.end();
1185
1186        unsigned high_thread = *list_begin;
1187
1188        activeThreads.erase(list_begin);
1189
1190        activeThreads.push_back(high_thread);
1191    }
1192}
1193
1194// Forward declaration of FullO3CPU.
1195template class FullO3CPU<AlphaSimpleImpl>;
1196