2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
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.
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.
32 #include "config/full_system.hh"
33 #include "config/use_checker.hh"
36 #include "sim/system.hh"
38 #include "sim/process.hh"
41 #include "cpu/activity.hh"
42 #include "cpu/simple_thread.hh"
43 #include "cpu/thread_context.hh"
44 #include "cpu/o3/isa_specific.hh"
45 #include "cpu/o3/cpu.hh"
47 #include "sim/root.hh"
48 #include "sim/stat_control.hh"
51 #include "cpu/checker/cpu.hh"
55 using namespace TheISA
;
57 BaseO3CPU::BaseO3CPU(Params
*params
)
58 : BaseCPU(params
), cpu_id(0)
69 FullO3CPU
<Impl
>::TickEvent::TickEvent(FullO3CPU
<Impl
> *c
)
70 : Event(&mainEventQueue
, CPU_Tick_Pri
), cpu(c
)
76 FullO3CPU
<Impl
>::TickEvent::process()
83 FullO3CPU
<Impl
>::TickEvent::description()
85 return "FullO3CPU tick event";
89 FullO3CPU
<Impl
>::ActivateThreadEvent::ActivateThreadEvent()
90 : Event(&mainEventQueue
, CPU_Tick_Pri
)
96 FullO3CPU
<Impl
>::ActivateThreadEvent::init(int thread_num
,
97 FullO3CPU
<Impl
> *thread_cpu
)
103 template <class Impl
>
105 FullO3CPU
<Impl
>::ActivateThreadEvent::process()
107 cpu
->activateThread(tid
);
110 template <class Impl
>
112 FullO3CPU
<Impl
>::ActivateThreadEvent::description()
114 return "FullO3CPU \"Activate Thread\" event";
117 template <class Impl
>
118 FullO3CPU
<Impl
>::FullO3CPU(Params
*params
)
121 removeInstsThisCycle(false),
128 regFile(params
->numPhysIntRegs
, params
->numPhysFloatRegs
),
130 freeList(params
->numberOfThreads
,
131 TheISA::NumIntRegs
, params
->numPhysIntRegs
,
132 TheISA::NumFloatRegs
, params
->numPhysFloatRegs
),
134 rob(params
->numROBEntries
, params
->squashWidth
,
135 params
->smtROBPolicy
, params
->smtROBThreshold
,
136 params
->numberOfThreads
),
138 scoreboard(params
->numberOfThreads
,
139 TheISA::NumIntRegs
, params
->numPhysIntRegs
,
140 TheISA::NumFloatRegs
, params
->numPhysFloatRegs
,
141 TheISA::NumMiscRegs
* number_of_threads
,
144 // For now just have these time buffers be pretty big.
145 // @todo: Make these time buffer sizes parameters or derived
152 activityRec(NumStages
, 10, params
->activity
),
157 system(params
->system
),
158 physmem(system
->physmem
),
159 #endif // FULL_SYSTEM
162 deferRegistration(params
->deferRegistration
),
163 numThreads(number_of_threads
)
169 if (params
->checker
) {
171 BaseCPU
*temp_checker
= params
->checker
;
172 checker
= dynamic_cast<Checker
<DynInstPtr
> *>(temp_checker
);
173 checker
->setMemory(mem
);
175 checker
->setSystem(params
->system
);
178 panic("Checker enabled but not compiled in!");
179 #endif // USE_CHECKER
183 thread
.resize(number_of_threads
);
184 tids
.resize(number_of_threads
);
187 // The stages also need their CPU pointer setup. However this
188 // must be done at the upper level CPU because they have pointers
189 // to the upper level CPU, and not this FullO3CPU.
191 // Set up Pointers to the activeThreads list for each stage
192 fetch
.setActiveThreads(&activeThreads
);
193 decode
.setActiveThreads(&activeThreads
);
194 rename
.setActiveThreads(&activeThreads
);
195 iew
.setActiveThreads(&activeThreads
);
196 commit
.setActiveThreads(&activeThreads
);
198 // Give each of the stages the time buffer they will use.
199 fetch
.setTimeBuffer(&timeBuffer
);
200 decode
.setTimeBuffer(&timeBuffer
);
201 rename
.setTimeBuffer(&timeBuffer
);
202 iew
.setTimeBuffer(&timeBuffer
);
203 commit
.setTimeBuffer(&timeBuffer
);
205 // Also setup each of the stages' queues.
206 fetch
.setFetchQueue(&fetchQueue
);
207 decode
.setFetchQueue(&fetchQueue
);
208 commit
.setFetchQueue(&fetchQueue
);
209 decode
.setDecodeQueue(&decodeQueue
);
210 rename
.setDecodeQueue(&decodeQueue
);
211 rename
.setRenameQueue(&renameQueue
);
212 iew
.setRenameQueue(&renameQueue
);
213 iew
.setIEWQueue(&iewQueue
);
214 commit
.setIEWQueue(&iewQueue
);
215 commit
.setRenameQueue(&renameQueue
);
217 commit
.setFetchStage(&fetch
);
218 commit
.setIEWStage(&iew
);
219 rename
.setIEWStage(&iew
);
220 rename
.setCommitStage(&commit
);
223 int active_threads
= params
->workload
.size();
225 if (active_threads
> Impl::MaxThreads
) {
226 panic("Workload Size too large. Increase the 'MaxThreads'"
227 "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or "
228 "edit your workload size.");
231 int active_threads
= 1;
234 //Make Sure That this a Valid Architeture
235 assert(params
->numPhysIntRegs
>= numThreads
* TheISA::NumIntRegs
);
236 assert(params
->numPhysFloatRegs
>= numThreads
* TheISA::NumFloatRegs
);
238 rename
.setScoreboard(&scoreboard
);
239 iew
.setScoreboard(&scoreboard
);
241 // Setup the rename map for whichever stages need it.
242 PhysRegIndex lreg_idx
= 0;
243 PhysRegIndex freg_idx
= params
->numPhysIntRegs
; //Index to 1 after int regs
245 for (int tid
=0; tid
< numThreads
; tid
++) {
246 bool bindRegs
= (tid
<= active_threads
- 1);
248 commitRenameMap
[tid
].init(TheISA::NumIntRegs
,
249 params
->numPhysIntRegs
,
250 lreg_idx
, //Index for Logical. Regs
252 TheISA::NumFloatRegs
,
253 params
->numPhysFloatRegs
,
254 freg_idx
, //Index for Float Regs
264 renameMap
[tid
].init(TheISA::NumIntRegs
,
265 params
->numPhysIntRegs
,
266 lreg_idx
, //Index for Logical. Regs
268 TheISA::NumFloatRegs
,
269 params
->numPhysFloatRegs
,
270 freg_idx
, //Index for Float Regs
281 rename
.setRenameMap(renameMap
);
282 commit
.setRenameMap(commitRenameMap
);
284 // Give renameMap & rename stage access to the freeList;
285 for (int i
=0; i
< numThreads
; i
++) {
286 renameMap
[i
].setFreeList(&freeList
);
288 rename
.setFreeList(&freeList
);
290 // Setup the ROB for whichever stages need it.
293 lastRunningCycle
= curTick
;
295 lastActivatedCycle
= -1;
297 contextSwitch
= false;
300 template <class Impl
>
301 FullO3CPU
<Impl
>::~FullO3CPU()
305 template <class Impl
>
307 FullO3CPU
<Impl
>::fullCPURegStats()
309 BaseO3CPU::regStats();
311 // Register any of the O3CPU's stats here.
313 .name(name() + ".timesIdled")
314 .desc("Number of times that the entire CPU went into an idle state and"
315 " unscheduled itself")
319 .name(name() + ".idleCycles")
320 .desc("Total number of cycles that the CPU has spent unscheduled due "
324 // Number of Instructions simulated
325 // --------------------------------
326 // Should probably be in Base CPU but need templated
327 // MaxThreads so put in here instead
330 .name(name() + ".committedInsts")
331 .desc("Number of Instructions Simulated");
334 .name(name() + ".committedInsts_total")
335 .desc("Number of Instructions Simulated");
338 .name(name() + ".cpi")
339 .desc("CPI: Cycles Per Instruction")
341 cpi
= simTicks
/ committedInsts
;
344 .name(name() + ".cpi_total")
345 .desc("CPI: Total CPI of All Threads")
347 totalCpi
= simTicks
/ totalCommittedInsts
;
350 .name(name() + ".ipc")
351 .desc("IPC: Instructions Per Cycle")
353 ipc
= committedInsts
/ simTicks
;
356 .name(name() + ".ipc_total")
357 .desc("IPC: Total IPC of All Threads")
359 totalIpc
= totalCommittedInsts
/ simTicks
;
363 template <class Impl
>
365 FullO3CPU
<Impl
>::tick()
367 DPRINTF(O3CPU
, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
373 //Tick each of the stages
388 // Now advance the time buffers
389 timeBuffer
.advance();
391 fetchQueue
.advance();
392 decodeQueue
.advance();
393 renameQueue
.advance();
396 activityRec
.advance();
398 if (removeInstsThisCycle
) {
399 cleanUpRemovedInsts();
402 if (!tickEvent
.scheduled()) {
403 if (_status
== SwitchedOut
) {
405 lastRunningCycle
= curTick
;
406 } else if (!activityRec
.active()) {
407 lastRunningCycle
= curTick
;
410 tickEvent
.schedule(curTick
+ cycles(1));
415 updateThreadPriority();
420 template <class Impl
>
422 FullO3CPU
<Impl
>::init()
424 if (!deferRegistration
) {
425 registerThreadContexts();
428 // Set inSyscall so that the CPU doesn't squash when initially
429 // setting up registers.
430 for (int i
= 0; i
< number_of_threads
; ++i
)
431 thread
[i
]->inSyscall
= true;
433 for (int tid
=0; tid
< number_of_threads
; tid
++) {
435 ThreadContext
*src_tc
= threadContexts
[tid
];
437 ThreadContext
*src_tc
= thread
[tid
]->getTC();
439 // Threads start in the Suspended State
440 if (src_tc
->status() != ThreadContext::Suspended
) {
445 TheISA::initCPU(src_tc
, src_tc
->readCpuId());
450 for (int i
= 0; i
< number_of_threads
; ++i
)
451 thread
[i
]->inSyscall
= false;
453 // Initialize stages.
459 commit
.setThreads(thread
);
462 template <class Impl
>
464 FullO3CPU
<Impl
>::insertThread(unsigned tid
)
466 DPRINTF(O3CPU
,"[tid:%i] Initializing thread into CPU");
467 // Will change now that the PC and thread state is internal to the CPU
468 // and not in the ThreadContext.
470 ThreadContext
*src_tc
= system
->threadContexts
[tid
];
472 ThreadContext
*src_tc
= tcBase(tid
);
475 //Bind Int Regs to Rename Map
476 for (int ireg
= 0; ireg
< TheISA::NumIntRegs
; ireg
++) {
477 PhysRegIndex phys_reg
= freeList
.getIntReg();
479 renameMap
[tid
].setEntry(ireg
,phys_reg
);
480 scoreboard
.setReg(phys_reg
);
483 //Bind Float Regs to Rename Map
484 for (int freg
= 0; freg
< TheISA::NumFloatRegs
; freg
++) {
485 PhysRegIndex phys_reg
= freeList
.getFloatReg();
487 renameMap
[tid
].setEntry(freg
,phys_reg
);
488 scoreboard
.setReg(phys_reg
);
491 //Copy Thread Data Into RegFile
492 //this->copyFromTC(tid);
495 setPC(src_tc
->readPC(), tid
);
496 setNextPC(src_tc
->readNextPC(), tid
);
497 #if THE_ISA != ALPHA_ISA
498 setNextNPC(src_tc
->readNextNPC(), tid
);
501 src_tc
->setStatus(ThreadContext::Active
);
503 activateContext(tid
,1);
505 //Reset ROB/IQ/LSQ Entries
506 commit
.rob
->resetEntries();
510 template <class Impl
>
512 FullO3CPU
<Impl
>::removeThread(unsigned tid
)
514 DPRINTF(O3CPU
,"[tid:%i] Removing thread from CPU.");
516 // Copy Thread Data From RegFile
517 // If thread is suspended, it might be re-allocated
518 //this->copyToTC(tid);
520 // Unbind Int Regs from Rename Map
521 for (int ireg
= 0; ireg
< TheISA::NumIntRegs
; ireg
++) {
522 PhysRegIndex phys_reg
= renameMap
[tid
].lookup(ireg
);
524 scoreboard
.unsetReg(phys_reg
);
525 freeList
.addReg(phys_reg
);
528 // Unbind Float Regs from Rename Map
529 for (int freg
= 0; freg
< TheISA::NumFloatRegs
; freg
++) {
530 PhysRegIndex phys_reg
= renameMap
[tid
].lookup(freg
);
532 scoreboard
.unsetReg(phys_reg
);
533 freeList
.addReg(phys_reg
);
536 // Squash Throughout Pipeline
541 assert(iew
.ldstQueue
.getCount(tid
) == 0);
543 // Reset ROB/IQ/LSQ Entries
544 if (activeThreads
.size() >= 1) {
545 commit
.rob
->resetEntries();
551 template <class Impl
>
553 FullO3CPU
<Impl
>::activateWhenReady(int tid
)
555 DPRINTF(O3CPU
,"[tid:%i]: Checking if resources are available for incoming"
556 "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
561 if (freeList
.numFreeIntRegs() >= TheISA::NumIntRegs
) {
562 DPRINTF(O3CPU
,"[tid:%i] Suspending thread due to not enough "
563 "Phys. Int. Regs.\n",
566 } else if (freeList
.numFreeFloatRegs() >= TheISA::NumFloatRegs
) {
567 DPRINTF(O3CPU
,"[tid:%i] Suspending thread due to not enough "
568 "Phys. Float. Regs.\n",
571 } else if (commit
.rob
->numFreeEntries() >=
572 commit
.rob
->entryAmount(activeThreads
.size() + 1)) {
573 DPRINTF(O3CPU
,"[tid:%i] Suspending thread due to not enough "
577 } else if (iew
.instQueue
.numFreeEntries() >=
578 iew
.instQueue
.entryAmount(activeThreads
.size() + 1)) {
579 DPRINTF(O3CPU
,"[tid:%i] Suspending thread due to not enough "
583 } else if (iew
.ldstQueue
.numFreeEntries() >=
584 iew
.ldstQueue
.entryAmount(activeThreads
.size() + 1)) {
585 DPRINTF(O3CPU
,"[tid:%i] Suspending thread due to not enough "
594 contextSwitch
= false;
596 cpuWaitList
.remove(tid
);
601 contextSwitch
= true;
604 cpuWaitList
.push_back(tid
);
608 template <class Impl
>
610 FullO3CPU
<Impl
>::activateThread(unsigned int tid
)
612 list
<unsigned>::iterator isActive
= find(
613 activeThreads
.begin(), activeThreads
.end(), tid
);
615 if (isActive
== activeThreads
.end()) {
616 DPRINTF(O3CPU
, "[tid:%i]: Adding to active threads list\n",
619 activeThreads
.push_back(tid
);
624 template <class Impl
>
626 FullO3CPU
<Impl
>::activateContext(int tid
, int delay
)
628 // Needs to set each stage to running as well.
630 DPRINTF(O3CPU
, "[tid:%i]: Scheduling thread context to activate "
631 "on cycle %d\n", tid
, curTick
+ cycles(delay
));
632 scheduleActivateThreadEvent(tid
, delay
);
637 if(lastActivatedCycle
< curTick
) {
638 scheduleTickEvent(delay
);
640 // Be sure to signal that there's some activity so the CPU doesn't
641 // deschedule itself.
642 activityRec
.activity();
643 fetch
.wakeFromQuiesce();
645 lastActivatedCycle
= curTick
;
651 template <class Impl
>
653 FullO3CPU
<Impl
>::suspendContext(int tid
)
655 DPRINTF(O3CPU
,"[tid: %i]: Suspending Thread Context.\n", tid
);
656 unscheduleTickEvent();
659 //Remove From Active List, if Active
660 list<unsigned>::iterator isActive = find(
661 activeThreads.begin(), activeThreads.end(), tid);
663 if (isActive != activeThreads.end()) {
664 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
666 activeThreads.erase(isActive);
671 template <class Impl
>
673 FullO3CPU
<Impl
>::deallocateContext(int tid
)
675 DPRINTF(O3CPU
,"[tid:%i]: Deallocating Thread Context", tid
);
677 //Remove From Active List, if Active
678 list
<unsigned>::iterator thread_it
=
679 find(activeThreads
.begin(), activeThreads
.end(), tid
);
681 if (thread_it
!= activeThreads
.end()) {
682 DPRINTF(O3CPU
,"[tid:%i]: Removing from active threads list\n",
684 activeThreads
.erase(thread_it
);
690 template <class Impl
>
692 FullO3CPU
<Impl
>::haltContext(int tid
)
694 DPRINTF(O3CPU
,"[tid:%i]: Halting Thread Context", tid
);
696 //Remove From Active List, if Active
697 list<unsigned>::iterator isActive = find(
698 activeThreads.begin(), activeThreads.end(), tid);
700 if (isActive != activeThreads.end()) {
701 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
703 activeThreads.erase(isActive);
710 template <class Impl
>
712 FullO3CPU
<Impl
>::drain(Event
*drain_event
)
715 drainEvent
= drain_event
;
722 // Wake the CPU and record activity so everything can drain out if
723 // the CPU is currently idle.
725 activityRec
.activity();
730 template <class Impl
>
732 FullO3CPU
<Impl
>::resume()
734 if (_status
== SwitchedOut
)
742 if (!tickEvent
.scheduled())
743 tickEvent
.schedule(curTick
);
747 template <class Impl
>
749 FullO3CPU
<Impl
>::signalDrained()
751 if (++drainCount
== NumStages
) {
752 if (tickEvent
.scheduled())
755 drainEvent
->process();
757 assert(drainCount
<= 5);
760 template <class Impl
>
762 FullO3CPU
<Impl
>::switchOut()
768 while (!removeList
.empty()) {
772 _status
= SwitchedOut
;
775 checker
->switchOut();
779 template <class Impl
>
781 FullO3CPU
<Impl
>::takeOverFrom(BaseCPU
*oldCPU
)
783 // Flush out any old data from the time buffers.
784 for (int i
= 0; i
< 10; ++i
) {
785 timeBuffer
.advance();
786 fetchQueue
.advance();
787 decodeQueue
.advance();
788 renameQueue
.advance();
794 BaseCPU::takeOverFrom(oldCPU
);
796 fetch
.takeOverFrom();
797 decode
.takeOverFrom();
798 rename
.takeOverFrom();
800 commit
.takeOverFrom();
802 assert(!tickEvent
.scheduled());
804 // @todo: Figure out how to properly select the tid to put onto
805 // the active threads list.
808 list
<unsigned>::iterator isActive
= find(
809 activeThreads
.begin(), activeThreads
.end(), tid
);
811 if (isActive
== activeThreads
.end()) {
812 //May Need to Re-code this if the delay variable is the delay
813 //needed for thread to activate
814 DPRINTF(O3CPU
, "Adding Thread %i to active threads list\n",
817 activeThreads
.push_back(tid
);
820 // Set all statuses to active, schedule the CPU's tick event.
821 // @todo: Fix up statuses so this is handled properly
822 for (int i
= 0; i
< threadContexts
.size(); ++i
) {
823 ThreadContext
*tc
= threadContexts
[i
];
824 if (tc
->status() == ThreadContext::Active
&& _status
!= Running
) {
826 tickEvent
.schedule(curTick
);
829 if (!tickEvent
.scheduled())
830 tickEvent
.schedule(curTick
);
833 template <class Impl
>
835 FullO3CPU
<Impl
>::readIntReg(int reg_idx
)
837 return regFile
.readIntReg(reg_idx
);
840 template <class Impl
>
842 FullO3CPU
<Impl
>::readFloatReg(int reg_idx
, int width
)
844 return regFile
.readFloatReg(reg_idx
, width
);
847 template <class Impl
>
849 FullO3CPU
<Impl
>::readFloatReg(int reg_idx
)
851 return regFile
.readFloatReg(reg_idx
);
854 template <class Impl
>
856 FullO3CPU
<Impl
>::readFloatRegBits(int reg_idx
, int width
)
858 return regFile
.readFloatRegBits(reg_idx
, width
);
861 template <class Impl
>
863 FullO3CPU
<Impl
>::readFloatRegBits(int reg_idx
)
865 return regFile
.readFloatRegBits(reg_idx
);
868 template <class Impl
>
870 FullO3CPU
<Impl
>::setIntReg(int reg_idx
, uint64_t val
)
872 regFile
.setIntReg(reg_idx
, val
);
875 template <class Impl
>
877 FullO3CPU
<Impl
>::setFloatReg(int reg_idx
, FloatReg val
, int width
)
879 regFile
.setFloatReg(reg_idx
, val
, width
);
882 template <class Impl
>
884 FullO3CPU
<Impl
>::setFloatReg(int reg_idx
, FloatReg val
)
886 regFile
.setFloatReg(reg_idx
, val
);
889 template <class Impl
>
891 FullO3CPU
<Impl
>::setFloatRegBits(int reg_idx
, FloatRegBits val
, int width
)
893 regFile
.setFloatRegBits(reg_idx
, val
, width
);
896 template <class Impl
>
898 FullO3CPU
<Impl
>::setFloatRegBits(int reg_idx
, FloatRegBits val
)
900 regFile
.setFloatRegBits(reg_idx
, val
);
903 template <class Impl
>
905 FullO3CPU
<Impl
>::readArchIntReg(int reg_idx
, unsigned tid
)
907 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
909 return regFile
.readIntReg(phys_reg
);
912 template <class Impl
>
914 FullO3CPU
<Impl
>::readArchFloatRegSingle(int reg_idx
, unsigned tid
)
916 int idx
= reg_idx
+ TheISA::FP_Base_DepTag
;
917 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(idx
);
919 return regFile
.readFloatReg(phys_reg
);
922 template <class Impl
>
924 FullO3CPU
<Impl
>::readArchFloatRegDouble(int reg_idx
, unsigned tid
)
926 int idx
= reg_idx
+ TheISA::FP_Base_DepTag
;
927 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(idx
);
929 return regFile
.readFloatReg(phys_reg
, 64);
932 template <class Impl
>
934 FullO3CPU
<Impl
>::readArchFloatRegInt(int reg_idx
, unsigned tid
)
936 int idx
= reg_idx
+ TheISA::FP_Base_DepTag
;
937 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(idx
);
939 return regFile
.readFloatRegBits(phys_reg
);
942 template <class Impl
>
944 FullO3CPU
<Impl
>::setArchIntReg(int reg_idx
, uint64_t val
, unsigned tid
)
946 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
948 regFile
.setIntReg(phys_reg
, val
);
951 template <class Impl
>
953 FullO3CPU
<Impl
>::setArchFloatRegSingle(int reg_idx
, float val
, unsigned tid
)
955 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
957 regFile
.setFloatReg(phys_reg
, val
);
960 template <class Impl
>
962 FullO3CPU
<Impl
>::setArchFloatRegDouble(int reg_idx
, double val
, unsigned tid
)
964 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
966 regFile
.setFloatReg(phys_reg
, val
, 64);
969 template <class Impl
>
971 FullO3CPU
<Impl
>::setArchFloatRegInt(int reg_idx
, uint64_t val
, unsigned tid
)
973 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
975 regFile
.setFloatRegBits(phys_reg
, val
);
978 template <class Impl
>
980 FullO3CPU
<Impl
>::readPC(unsigned tid
)
982 return commit
.readPC(tid
);
985 template <class Impl
>
987 FullO3CPU
<Impl
>::setPC(Addr new_PC
,unsigned tid
)
989 commit
.setPC(new_PC
, tid
);
992 template <class Impl
>
994 FullO3CPU
<Impl
>::readNextPC(unsigned tid
)
996 return commit
.readNextPC(tid
);
999 template <class Impl
>
1001 FullO3CPU
<Impl
>::setNextPC(uint64_t val
,unsigned tid
)
1003 commit
.setNextPC(val
, tid
);
1006 #if THE_ISA != ALPHA_ISA
1007 template <class Impl
>
1009 FullO3CPU
<Impl
>::readNextNPC(unsigned tid
)
1011 return commit
.readNextNPC(tid
);
1014 template <class Impl
>
1016 FullO3CPU
<Impl
>::setNextNNPC(uint64_t val
,unsigned tid
)
1018 commit
.setNextNPC(val
, tid
);
1022 template <class Impl
>
1023 typename FullO3CPU
<Impl
>::ListIt
1024 FullO3CPU
<Impl
>::addInst(DynInstPtr
&inst
)
1026 instList
.push_back(inst
);
1028 return --(instList
.end());
1031 template <class Impl
>
1033 FullO3CPU
<Impl
>::instDone(unsigned tid
)
1035 // Keep an instruction count.
1036 thread
[tid
]->numInst
++;
1037 thread
[tid
]->numInsts
++;
1038 committedInsts
[tid
]++;
1039 totalCommittedInsts
++;
1041 // Check for instruction-count-based events.
1042 comInstEventQueue
[tid
]->serviceEvents(thread
[tid
]->numInst
);
1045 template <class Impl
>
1047 FullO3CPU
<Impl
>::addToRemoveList(DynInstPtr
&inst
)
1049 removeInstsThisCycle
= true;
1051 removeList
.push(inst
->getInstListIt());
1054 template <class Impl
>
1056 FullO3CPU
<Impl
>::removeFrontInst(DynInstPtr
&inst
)
1058 DPRINTF(O3CPU
, "Removing committed instruction [tid:%i] PC %#x "
1060 inst
->threadNumber
, inst
->readPC(), inst
->seqNum
);
1062 removeInstsThisCycle
= true;
1064 // Remove the front instruction.
1065 removeList
.push(inst
->getInstListIt());
1068 template <class Impl
>
1070 FullO3CPU
<Impl
>::removeInstsNotInROB(unsigned tid
)
1072 DPRINTF(O3CPU
, "Thread %i: Deleting instructions from instruction"
1077 bool rob_empty
= false;
1079 if (instList
.empty()) {
1081 } else if (rob
.isEmpty(/*tid*/)) {
1082 DPRINTF(O3CPU
, "ROB is empty, squashing all insts.\n");
1083 end_it
= instList
.begin();
1086 end_it
= (rob
.readTailInst(tid
))->getInstListIt();
1087 DPRINTF(O3CPU
, "ROB is not empty, squashing insts not in ROB.\n");
1090 removeInstsThisCycle
= true;
1092 ListIt inst_it
= instList
.end();
1096 // Walk through the instruction list, removing any instructions
1097 // that were inserted after the given instruction iterator, end_it.
1098 while (inst_it
!= end_it
) {
1099 assert(!instList
.empty());
1101 squashInstIt(inst_it
, tid
);
1106 // If the ROB was empty, then we actually need to remove the first
1107 // instruction as well.
1109 squashInstIt(inst_it
, tid
);
1113 template <class Impl
>
1115 FullO3CPU
<Impl
>::removeInstsUntil(const InstSeqNum
&seq_num
,
1118 assert(!instList
.empty());
1120 removeInstsThisCycle
= true;
1122 ListIt inst_iter
= instList
.end();
1126 DPRINTF(O3CPU
, "Deleting instructions from instruction "
1127 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1128 tid
, seq_num
, (*inst_iter
)->seqNum
);
1130 while ((*inst_iter
)->seqNum
> seq_num
) {
1132 bool break_loop
= (inst_iter
== instList
.begin());
1134 squashInstIt(inst_iter
, tid
);
1143 template <class Impl
>
1145 FullO3CPU
<Impl
>::squashInstIt(const ListIt
&instIt
, const unsigned &tid
)
1147 if ((*instIt
)->threadNumber
== tid
) {
1148 DPRINTF(O3CPU
, "Squashing instruction, "
1149 "[tid:%i] [sn:%lli] PC %#x\n",
1150 (*instIt
)->threadNumber
,
1152 (*instIt
)->readPC());
1154 // Mark it as squashed.
1155 (*instIt
)->setSquashed();
1157 // @todo: Formulate a consistent method for deleting
1158 // instructions from the instruction list
1159 // Remove the instruction from the list.
1160 removeList
.push(instIt
);
1164 template <class Impl
>
1166 FullO3CPU
<Impl
>::cleanUpRemovedInsts()
1168 while (!removeList
.empty()) {
1169 DPRINTF(O3CPU
, "Removing instruction, "
1170 "[tid:%i] [sn:%lli] PC %#x\n",
1171 (*removeList
.front())->threadNumber
,
1172 (*removeList
.front())->seqNum
,
1173 (*removeList
.front())->readPC());
1175 instList
.erase(removeList
.front());
1180 removeInstsThisCycle
= false;
1183 template <class Impl>
1185 FullO3CPU<Impl>::removeAllInsts()
1190 template <class Impl
>
1192 FullO3CPU
<Impl
>::dumpInsts()
1196 ListIt inst_list_it
= instList
.begin();
1198 cprintf("Dumping Instruction List\n");
1200 while (inst_list_it
!= instList
.end()) {
1201 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1203 num
, (*inst_list_it
)->readPC(), (*inst_list_it
)->threadNumber
,
1204 (*inst_list_it
)->seqNum
, (*inst_list_it
)->isIssued(),
1205 (*inst_list_it
)->isSquashed());
1211 template <class Impl>
1213 FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
1215 iew.wakeDependents(inst);
1218 template <class Impl
>
1220 FullO3CPU
<Impl
>::wakeCPU()
1222 if (activityRec
.active() || tickEvent
.scheduled()) {
1223 DPRINTF(Activity
, "CPU already running.\n");
1227 DPRINTF(Activity
, "Waking up CPU\n");
1229 idleCycles
+= (curTick
- 1) - lastRunningCycle
;
1231 tickEvent
.schedule(curTick
);
1234 template <class Impl
>
1236 FullO3CPU
<Impl
>::getFreeTid()
1238 for (int i
=0; i
< numThreads
; i
++) {
1248 template <class Impl
>
1250 FullO3CPU
<Impl
>::doContextSwitch()
1252 if (contextSwitch
) {
1254 //ADD CODE TO DEACTIVE THREAD HERE (???)
1256 for (int tid
=0; tid
< cpuWaitList
.size(); tid
++) {
1257 activateWhenReady(tid
);
1260 if (cpuWaitList
.size() == 0)
1261 contextSwitch
= true;
1265 template <class Impl
>
1267 FullO3CPU
<Impl
>::updateThreadPriority()
1269 if (activeThreads
.size() > 1)
1271 //DEFAULT TO ROUND ROBIN SCHEME
1272 //e.g. Move highest priority to end of thread list
1273 list
<unsigned>::iterator list_begin
= activeThreads
.begin();
1274 list
<unsigned>::iterator list_end
= activeThreads
.end();
1276 unsigned high_thread
= *list_begin
;
1278 activeThreads
.erase(list_begin
);
1280 activeThreads
.push_back(high_thread
);
1284 // Forward declaration of FullO3CPU.
1285 template class FullO3CPU
<O3CPUImpl
>;