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