2 * Copyright (c) 2011-2012, 2014, 2016, 2017, 2019 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
15 * Copyright (c) 2004-2006 The Regents of The University of Michigan
16 * Copyright (c) 2011 Regents of the University of California
17 * All rights reserved.
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions are
21 * met: redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer;
23 * redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution;
26 * neither the name of the copyright holders nor the names of its
27 * contributors may be used to endorse or promote products derived from
28 * this software without specific prior written permission.
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 #include "cpu/o3/cpu.hh"
49 #include "arch/generic/traits.hh"
50 #include "arch/kernel_stats.hh"
51 #include "config/the_isa.hh"
52 #include "cpu/activity.hh"
53 #include "cpu/checker/cpu.hh"
54 #include "cpu/checker/thread_context.hh"
55 #include "cpu/o3/isa_specific.hh"
56 #include "cpu/o3/thread_context.hh"
57 #include "cpu/quiesce_event.hh"
58 #include "cpu/simple_thread.hh"
59 #include "cpu/thread_context.hh"
60 #include "debug/Activity.hh"
61 #include "debug/Drain.hh"
62 #include "debug/O3CPU.hh"
63 #include "debug/Quiesce.hh"
64 #include "enums/MemoryMode.hh"
65 #include "sim/core.hh"
66 #include "sim/full_system.hh"
67 #include "sim/process.hh"
68 #include "sim/stat_control.hh"
69 #include "sim/system.hh"
71 #if THE_ISA == ALPHA_ISA
72 #include "arch/alpha/osfpal.hh"
73 #include "debug/Activity.hh"
79 using namespace TheISA
;
82 BaseO3CPU::BaseO3CPU(BaseCPUParams
*params
)
95 FullO3CPU
<Impl
>::IcachePort::recvTimingResp(PacketPtr pkt
)
97 DPRINTF(O3CPU
, "Fetch unit received timing\n");
98 // We shouldn't ever get a cacheable block in Modified state
99 assert(pkt
->req
->isUncacheable() ||
100 !(pkt
->cacheResponding() && !pkt
->hasSharers()));
101 fetch
->processCacheCompletion(pkt
);
108 FullO3CPU
<Impl
>::IcachePort::recvReqRetry()
110 fetch
->recvReqRetry();
113 template <class Impl
>
115 FullO3CPU
<Impl
>::DcachePort::recvTimingResp(PacketPtr pkt
)
117 return lsq
->recvTimingResp(pkt
);
120 template <class Impl
>
122 FullO3CPU
<Impl
>::DcachePort::recvTimingSnoopReq(PacketPtr pkt
)
124 for (ThreadID tid
= 0; tid
< cpu
->numThreads
; tid
++) {
125 if (cpu
->getCpuAddrMonitor(tid
)->doMonitor(pkt
)) {
129 lsq
->recvTimingSnoopReq(pkt
);
132 template <class Impl
>
134 FullO3CPU
<Impl
>::DcachePort::recvReqRetry()
139 template <class Impl
>
140 FullO3CPU
<Impl
>::FullO3CPU(DerivO3CPUParams
*params
)
144 tickEvent([this]{ tick(); }, "FullO3CPU tick",
145 false, Event::CPU_Tick_Pri
),
149 removeInstsThisCycle(false),
151 decode(this, params
),
152 rename(this, params
),
154 commit(this, params
),
156 /* It is mandatory that all SMT threads use the same renaming mode as
157 * they are sharing registers and rename */
158 vecMode(RenameMode
<TheISA::ISA
>::init(params
->isa
[0])),
159 regFile(params
->numPhysIntRegs
,
160 params
->numPhysFloatRegs
,
161 params
->numPhysVecRegs
,
162 params
->numPhysVecPredRegs
,
163 params
->numPhysCCRegs
,
166 freeList(name() + ".freelist", ®File
),
170 scoreboard(name() + ".scoreboard",
171 regFile
.totalNumPhysRegs()),
173 isa(numThreads
, NULL
),
175 icachePort(&fetch
, this),
176 dcachePort(&iew
.ldstQueue
, this),
178 timeBuffer(params
->backComSize
, params
->forwardComSize
),
179 fetchQueue(params
->backComSize
, params
->forwardComSize
),
180 decodeQueue(params
->backComSize
, params
->forwardComSize
),
181 renameQueue(params
->backComSize
, params
->forwardComSize
),
182 iewQueue(params
->backComSize
, params
->forwardComSize
),
183 activityRec(name(), NumStages
,
184 params
->backComSize
+ params
->forwardComSize
,
188 system(params
->system
),
189 lastRunningCycle(curCycle())
191 if (!params
->switched_out
) {
194 _status
= SwitchedOut
;
197 if (params
->checker
) {
198 BaseCPU
*temp_checker
= params
->checker
;
199 checker
= dynamic_cast<Checker
<Impl
> *>(temp_checker
);
200 checker
->setIcachePort(&icachePort
);
201 checker
->setSystem(params
->system
);
207 thread
.resize(numThreads
);
208 tids
.resize(numThreads
);
211 // The stages also need their CPU pointer setup. However this
212 // must be done at the upper level CPU because they have pointers
213 // to the upper level CPU, and not this FullO3CPU.
215 // Set up Pointers to the activeThreads list for each stage
216 fetch
.setActiveThreads(&activeThreads
);
217 decode
.setActiveThreads(&activeThreads
);
218 rename
.setActiveThreads(&activeThreads
);
219 iew
.setActiveThreads(&activeThreads
);
220 commit
.setActiveThreads(&activeThreads
);
222 // Give each of the stages the time buffer they will use.
223 fetch
.setTimeBuffer(&timeBuffer
);
224 decode
.setTimeBuffer(&timeBuffer
);
225 rename
.setTimeBuffer(&timeBuffer
);
226 iew
.setTimeBuffer(&timeBuffer
);
227 commit
.setTimeBuffer(&timeBuffer
);
229 // Also setup each of the stages' queues.
230 fetch
.setFetchQueue(&fetchQueue
);
231 decode
.setFetchQueue(&fetchQueue
);
232 commit
.setFetchQueue(&fetchQueue
);
233 decode
.setDecodeQueue(&decodeQueue
);
234 rename
.setDecodeQueue(&decodeQueue
);
235 rename
.setRenameQueue(&renameQueue
);
236 iew
.setRenameQueue(&renameQueue
);
237 iew
.setIEWQueue(&iewQueue
);
238 commit
.setIEWQueue(&iewQueue
);
239 commit
.setRenameQueue(&renameQueue
);
241 commit
.setIEWStage(&iew
);
242 rename
.setIEWStage(&iew
);
243 rename
.setCommitStage(&commit
);
245 ThreadID active_threads
;
249 active_threads
= params
->workload
.size();
251 if (active_threads
> Impl::MaxThreads
) {
252 panic("Workload Size too large. Increase the 'MaxThreads' "
253 "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) "
254 "or edit your workload size.");
258 //Make Sure That this a Valid Architeture
259 assert(params
->numPhysIntRegs
>= numThreads
* TheISA::NumIntRegs
);
260 assert(params
->numPhysFloatRegs
>= numThreads
* TheISA::NumFloatRegs
);
261 assert(params
->numPhysVecRegs
>= numThreads
* TheISA::NumVecRegs
);
262 assert(params
->numPhysVecPredRegs
>= numThreads
* TheISA::NumVecPredRegs
);
263 assert(params
->numPhysCCRegs
>= numThreads
* TheISA::NumCCRegs
);
265 rename
.setScoreboard(&scoreboard
);
266 iew
.setScoreboard(&scoreboard
);
268 // Setup the rename map for whichever stages need it.
269 for (ThreadID tid
= 0; tid
< numThreads
; tid
++) {
270 isa
[tid
] = params
->isa
[tid
];
271 assert(RenameMode
<TheISA::ISA
>::equalsInit(isa
[tid
], isa
[0]));
273 // Only Alpha has an FP zero register, so for other ISAs we
274 // use an invalid FP register index to avoid special treatment
275 // of any valid FP reg.
276 RegIndex invalidFPReg
= TheISA::NumFloatRegs
+ 1;
278 (THE_ISA
== ALPHA_ISA
) ? TheISA::ZeroReg
: invalidFPReg
;
280 commitRenameMap
[tid
].init(®File
, TheISA::ZeroReg
, fpZeroReg
,
284 renameMap
[tid
].init(®File
, TheISA::ZeroReg
, fpZeroReg
,
288 // Initialize rename map to assign physical registers to the
289 // architectural registers for active threads only.
290 for (ThreadID tid
= 0; tid
< active_threads
; tid
++) {
291 for (RegIndex ridx
= 0; ridx
< TheISA::NumIntRegs
; ++ridx
) {
292 // Note that we can't use the rename() method because we don't
293 // want special treatment for the zero register at this point
294 PhysRegIdPtr phys_reg
= freeList
.getIntReg();
295 renameMap
[tid
].setEntry(RegId(IntRegClass
, ridx
), phys_reg
);
296 commitRenameMap
[tid
].setEntry(RegId(IntRegClass
, ridx
), phys_reg
);
299 for (RegIndex ridx
= 0; ridx
< TheISA::NumFloatRegs
; ++ridx
) {
300 PhysRegIdPtr phys_reg
= freeList
.getFloatReg();
301 renameMap
[tid
].setEntry(RegId(FloatRegClass
, ridx
), phys_reg
);
302 commitRenameMap
[tid
].setEntry(
303 RegId(FloatRegClass
, ridx
), phys_reg
);
306 /* Here we need two 'interfaces' the 'whole register' and the
307 * 'register element'. At any point only one of them will be
309 if (vecMode
== Enums::Full
) {
310 /* Initialize the full-vector interface */
311 for (RegIndex ridx
= 0; ridx
< TheISA::NumVecRegs
; ++ridx
) {
312 RegId rid
= RegId(VecRegClass
, ridx
);
313 PhysRegIdPtr phys_reg
= freeList
.getVecReg();
314 renameMap
[tid
].setEntry(rid
, phys_reg
);
315 commitRenameMap
[tid
].setEntry(rid
, phys_reg
);
318 /* Initialize the vector-element interface */
319 for (RegIndex ridx
= 0; ridx
< TheISA::NumVecRegs
; ++ridx
) {
320 for (ElemIndex ldx
= 0; ldx
< TheISA::NumVecElemPerVecReg
;
322 RegId lrid
= RegId(VecElemClass
, ridx
, ldx
);
323 PhysRegIdPtr phys_elem
= freeList
.getVecElem();
324 renameMap
[tid
].setEntry(lrid
, phys_elem
);
325 commitRenameMap
[tid
].setEntry(lrid
, phys_elem
);
330 for (RegIndex ridx
= 0; ridx
< TheISA::NumVecPredRegs
; ++ridx
) {
331 PhysRegIdPtr phys_reg
= freeList
.getVecPredReg();
332 renameMap
[tid
].setEntry(RegId(VecPredRegClass
, ridx
), phys_reg
);
333 commitRenameMap
[tid
].setEntry(
334 RegId(VecPredRegClass
, ridx
), phys_reg
);
337 for (RegIndex ridx
= 0; ridx
< TheISA::NumCCRegs
; ++ridx
) {
338 PhysRegIdPtr phys_reg
= freeList
.getCCReg();
339 renameMap
[tid
].setEntry(RegId(CCRegClass
, ridx
), phys_reg
);
340 commitRenameMap
[tid
].setEntry(RegId(CCRegClass
, ridx
), phys_reg
);
344 rename
.setRenameMap(renameMap
);
345 commit
.setRenameMap(commitRenameMap
);
346 rename
.setFreeList(&freeList
);
348 // Setup the ROB for whichever stages need it.
351 lastActivatedCycle
= 0;
353 // Give renameMap & rename stage access to the freeList;
354 for (ThreadID tid
= 0; tid
< numThreads
; tid
++)
355 globalSeqNum
[tid
] = 1;
358 DPRINTF(O3CPU
, "Creating O3CPU object.\n");
360 // Setup any thread state.
361 this->thread
.resize(this->numThreads
);
363 for (ThreadID tid
= 0; tid
< this->numThreads
; ++tid
) {
365 // SMT is not supported in FS mode yet.
366 assert(this->numThreads
== 1);
367 this->thread
[tid
] = new Thread(this, 0, NULL
);
369 if (tid
< params
->workload
.size()) {
370 DPRINTF(O3CPU
, "Workload[%i] process is %#x",
371 tid
, this->thread
[tid
]);
372 this->thread
[tid
] = new typename FullO3CPU
<Impl
>::Thread(
373 (typename
Impl::O3CPU
*)(this),
374 tid
, params
->workload
[tid
]);
376 //usedTids[tid] = true;
377 //threadMap[tid] = tid;
379 //Allocate Empty thread so M5 can use later
380 //when scheduling threads to CPU
381 Process
* dummy_proc
= NULL
;
383 this->thread
[tid
] = new typename FullO3CPU
<Impl
>::Thread(
384 (typename
Impl::O3CPU
*)(this),
386 //usedTids[tid] = false;
392 // Setup the TC that will serve as the interface to the threads/CPU.
393 O3ThreadContext
<Impl
> *o3_tc
= new O3ThreadContext
<Impl
>;
397 // If we're using a checker, then the TC should be the
398 // CheckerThreadContext.
399 if (params
->checker
) {
400 tc
= new CheckerThreadContext
<O3ThreadContext
<Impl
> >(
401 o3_tc
, this->checker
);
404 o3_tc
->cpu
= (typename
Impl::O3CPU
*)(this);
406 o3_tc
->thread
= this->thread
[tid
];
408 // Setup quiesce event.
409 this->thread
[tid
]->quiesceEvent
= new EndQuiesceEvent(tc
);
411 // Give the thread the TC.
412 this->thread
[tid
]->tc
= tc
;
414 // Add the TC to the CPU's list of TC's.
415 this->threadContexts
.push_back(tc
);
418 // FullO3CPU always requires an interrupt controller.
419 if (!params
->switched_out
&& interrupts
.empty()) {
420 fatal("FullO3CPU %s has no interrupt controller.\n"
421 "Ensure createInterruptController() is called.\n", name());
424 for (ThreadID tid
= 0; tid
< this->numThreads
; tid
++)
425 this->thread
[tid
]->setFuncExeInst(0);
428 template <class Impl
>
429 FullO3CPU
<Impl
>::~FullO3CPU()
433 template <class Impl
>
435 FullO3CPU
<Impl
>::regProbePoints()
437 BaseCPU::regProbePoints();
439 ppInstAccessComplete
= new ProbePointArg
<PacketPtr
>(getProbeManager(), "InstAccessComplete");
440 ppDataAccessComplete
= new ProbePointArg
<std::pair
<DynInstPtr
, PacketPtr
> >(getProbeManager(), "DataAccessComplete");
442 fetch
.regProbePoints();
443 rename
.regProbePoints();
444 iew
.regProbePoints();
445 commit
.regProbePoints();
448 template <class Impl
>
450 FullO3CPU
<Impl
>::regStats()
452 BaseO3CPU::regStats();
454 // Register any of the O3CPU's stats here.
456 .name(name() + ".timesIdled")
457 .desc("Number of times that the entire CPU went into an idle state and"
458 " unscheduled itself")
462 .name(name() + ".idleCycles")
463 .desc("Total number of cycles that the CPU has spent unscheduled due "
468 .name(name() + ".quiesceCycles")
469 .desc("Total number of cycles that CPU has spent quiesced or waiting "
471 .prereq(quiesceCycles
);
473 // Number of Instructions simulated
474 // --------------------------------
475 // Should probably be in Base CPU but need templated
476 // MaxThreads so put in here instead
479 .name(name() + ".committedInsts")
480 .desc("Number of Instructions Simulated")
481 .flags(Stats::total
);
485 .name(name() + ".committedOps")
486 .desc("Number of Ops (including micro ops) Simulated")
487 .flags(Stats::total
);
490 .name(name() + ".cpi")
491 .desc("CPI: Cycles Per Instruction")
493 cpi
= numCycles
/ committedInsts
;
496 .name(name() + ".cpi_total")
497 .desc("CPI: Total CPI of All Threads")
499 totalCpi
= numCycles
/ sum(committedInsts
);
502 .name(name() + ".ipc")
503 .desc("IPC: Instructions Per Cycle")
505 ipc
= committedInsts
/ numCycles
;
508 .name(name() + ".ipc_total")
509 .desc("IPC: Total IPC of All Threads")
511 totalIpc
= sum(committedInsts
) / numCycles
;
513 this->fetch
.regStats();
514 this->decode
.regStats();
515 this->rename
.regStats();
516 this->iew
.regStats();
517 this->commit
.regStats();
518 this->rob
.regStats();
521 .name(name() + ".int_regfile_reads")
522 .desc("number of integer regfile reads")
523 .prereq(intRegfileReads
);
526 .name(name() + ".int_regfile_writes")
527 .desc("number of integer regfile writes")
528 .prereq(intRegfileWrites
);
531 .name(name() + ".fp_regfile_reads")
532 .desc("number of floating regfile reads")
533 .prereq(fpRegfileReads
);
536 .name(name() + ".fp_regfile_writes")
537 .desc("number of floating regfile writes")
538 .prereq(fpRegfileWrites
);
541 .name(name() + ".vec_regfile_reads")
542 .desc("number of vector regfile reads")
543 .prereq(vecRegfileReads
);
546 .name(name() + ".vec_regfile_writes")
547 .desc("number of vector regfile writes")
548 .prereq(vecRegfileWrites
);
551 .name(name() + ".pred_regfile_reads")
552 .desc("number of predicate regfile reads")
553 .prereq(vecPredRegfileReads
);
556 .name(name() + ".pred_regfile_writes")
557 .desc("number of predicate regfile writes")
558 .prereq(vecPredRegfileWrites
);
561 .name(name() + ".cc_regfile_reads")
562 .desc("number of cc regfile reads")
563 .prereq(ccRegfileReads
);
566 .name(name() + ".cc_regfile_writes")
567 .desc("number of cc regfile writes")
568 .prereq(ccRegfileWrites
);
571 .name(name() + ".misc_regfile_reads")
572 .desc("number of misc regfile reads")
573 .prereq(miscRegfileReads
);
576 .name(name() + ".misc_regfile_writes")
577 .desc("number of misc regfile writes")
578 .prereq(miscRegfileWrites
);
581 template <class Impl
>
583 FullO3CPU
<Impl
>::tick()
585 DPRINTF(O3CPU
, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
586 assert(!switchedOut());
587 assert(drainState() != DrainState::Drained
);
590 updateCycleCounters(BaseCPU::CPU_STATE_ON
);
594 //Tick each of the stages
605 // Now advance the time buffers
606 timeBuffer
.advance();
608 fetchQueue
.advance();
609 decodeQueue
.advance();
610 renameQueue
.advance();
613 activityRec
.advance();
615 if (removeInstsThisCycle
) {
616 cleanUpRemovedInsts();
619 if (!tickEvent
.scheduled()) {
620 if (_status
== SwitchedOut
) {
621 DPRINTF(O3CPU
, "Switched out!\n");
623 lastRunningCycle
= curCycle();
624 } else if (!activityRec
.active() || _status
== Idle
) {
625 DPRINTF(O3CPU
, "Idle!\n");
626 lastRunningCycle
= curCycle();
629 schedule(tickEvent
, clockEdge(Cycles(1)));
630 DPRINTF(O3CPU
, "Scheduling next tick!\n");
635 updateThreadPriority();
640 template <class Impl
>
642 FullO3CPU
<Impl
>::init()
646 for (ThreadID tid
= 0; tid
< numThreads
; ++tid
) {
647 // Set noSquashFromTC so that the CPU doesn't squash when initially
648 // setting up registers.
649 thread
[tid
]->noSquashFromTC
= true;
650 // Initialise the ThreadContext's memory proxies
651 thread
[tid
]->initMemProxies(thread
[tid
]->getTC());
654 if (FullSystem
&& !params()->switched_out
) {
655 for (ThreadID tid
= 0; tid
< numThreads
; tid
++) {
656 ThreadContext
*src_tc
= threadContexts
[tid
];
657 TheISA::initCPU(src_tc
, src_tc
->contextId());
661 // Clear noSquashFromTC.
662 for (int tid
= 0; tid
< numThreads
; ++tid
)
663 thread
[tid
]->noSquashFromTC
= false;
665 commit
.setThreads(thread
);
668 template <class Impl
>
670 FullO3CPU
<Impl
>::startup()
673 for (int tid
= 0; tid
< numThreads
; ++tid
)
674 isa
[tid
]->startup(threadContexts
[tid
]);
676 fetch
.startupStage();
677 decode
.startupStage();
679 rename
.startupStage();
680 commit
.startupStage();
683 template <class Impl
>
685 FullO3CPU
<Impl
>::activateThread(ThreadID tid
)
687 list
<ThreadID
>::iterator isActive
=
688 std::find(activeThreads
.begin(), activeThreads
.end(), tid
);
690 DPRINTF(O3CPU
, "[tid:%i]: Calling activate thread.\n", tid
);
691 assert(!switchedOut());
693 if (isActive
== activeThreads
.end()) {
694 DPRINTF(O3CPU
, "[tid:%i]: Adding to active threads list\n",
697 activeThreads
.push_back(tid
);
701 template <class Impl
>
703 FullO3CPU
<Impl
>::deactivateThread(ThreadID tid
)
705 //Remove From Active List, if Active
706 list
<ThreadID
>::iterator thread_it
=
707 std::find(activeThreads
.begin(), activeThreads
.end(), tid
);
709 DPRINTF(O3CPU
, "[tid:%i]: Calling deactivate thread.\n", tid
);
710 assert(!switchedOut());
712 if (thread_it
!= activeThreads
.end()) {
713 DPRINTF(O3CPU
,"[tid:%i]: Removing from active threads list\n",
715 activeThreads
.erase(thread_it
);
718 fetch
.deactivateThread(tid
);
719 commit
.deactivateThread(tid
);
722 template <class Impl
>
724 FullO3CPU
<Impl
>::totalInsts() const
728 ThreadID size
= thread
.size();
729 for (ThreadID i
= 0; i
< size
; i
++)
730 total
+= thread
[i
]->numInst
;
735 template <class Impl
>
737 FullO3CPU
<Impl
>::totalOps() const
741 ThreadID size
= thread
.size();
742 for (ThreadID i
= 0; i
< size
; i
++)
743 total
+= thread
[i
]->numOp
;
748 template <class Impl
>
750 FullO3CPU
<Impl
>::activateContext(ThreadID tid
)
752 assert(!switchedOut());
754 // Needs to set each stage to running as well.
757 // We don't want to wake the CPU if it is drained. In that case,
758 // we just want to flag the thread as active and schedule the tick
759 // event from drainResume() instead.
760 if (drainState() == DrainState::Drained
)
763 // If we are time 0 or if the last activation time is in the past,
764 // schedule the next tick and wake up the fetch unit
765 if (lastActivatedCycle
== 0 || lastActivatedCycle
< curTick()) {
766 scheduleTickEvent(Cycles(0));
768 // Be sure to signal that there's some activity so the CPU doesn't
769 // deschedule itself.
770 activityRec
.activity();
771 fetch
.wakeFromQuiesce();
773 Cycles
cycles(curCycle() - lastRunningCycle
);
774 // @todo: This is an oddity that is only here to match the stats
777 quiesceCycles
+= cycles
;
779 lastActivatedCycle
= curTick();
783 BaseCPU::activateContext(tid
);
787 template <class Impl
>
789 FullO3CPU
<Impl
>::suspendContext(ThreadID tid
)
791 DPRINTF(O3CPU
,"[tid: %i]: Suspending Thread Context.\n", tid
);
792 assert(!switchedOut());
794 deactivateThread(tid
);
796 // If this was the last thread then unschedule the tick event.
797 if (activeThreads
.size() == 0) {
798 unscheduleTickEvent();
799 lastRunningCycle
= curCycle();
803 DPRINTF(Quiesce
, "Suspending Context\n");
805 BaseCPU::suspendContext(tid
);
808 template <class Impl
>
810 FullO3CPU
<Impl
>::haltContext(ThreadID tid
)
812 //For now, this is the same as deallocate
813 DPRINTF(O3CPU
,"[tid:%i]: Halt Context called. Deallocating", tid
);
814 assert(!switchedOut());
816 deactivateThread(tid
);
819 updateCycleCounters(BaseCPU::CPU_STATE_SLEEP
);
822 template <class Impl
>
824 FullO3CPU
<Impl
>::insertThread(ThreadID tid
)
826 DPRINTF(O3CPU
,"[tid:%i] Initializing thread into CPU");
827 // Will change now that the PC and thread state is internal to the CPU
828 // and not in the ThreadContext.
829 ThreadContext
*src_tc
;
831 src_tc
= system
->threadContexts
[tid
];
833 src_tc
= tcBase(tid
);
835 //Bind Int Regs to Rename Map
837 for (RegId
reg_id(IntRegClass
, 0); reg_id
.index() < TheISA::NumIntRegs
;
839 PhysRegIdPtr phys_reg
= freeList
.getIntReg();
840 renameMap
[tid
].setEntry(reg_id
, phys_reg
);
841 scoreboard
.setReg(phys_reg
);
844 //Bind Float Regs to Rename Map
845 for (RegId
reg_id(FloatRegClass
, 0); reg_id
.index() < TheISA::NumFloatRegs
;
847 PhysRegIdPtr phys_reg
= freeList
.getFloatReg();
848 renameMap
[tid
].setEntry(reg_id
, phys_reg
);
849 scoreboard
.setReg(phys_reg
);
852 //Bind condition-code Regs to Rename Map
853 for (RegId
reg_id(CCRegClass
, 0); reg_id
.index() < TheISA::NumCCRegs
;
855 PhysRegIdPtr phys_reg
= freeList
.getCCReg();
856 renameMap
[tid
].setEntry(reg_id
, phys_reg
);
857 scoreboard
.setReg(phys_reg
);
860 //Copy Thread Data Into RegFile
861 //this->copyFromTC(tid);
864 pcState(src_tc
->pcState(), tid
);
866 src_tc
->setStatus(ThreadContext::Active
);
868 activateContext(tid
);
870 //Reset ROB/IQ/LSQ Entries
871 commit
.rob
->resetEntries();
874 template <class Impl
>
876 FullO3CPU
<Impl
>::removeThread(ThreadID tid
)
878 DPRINTF(O3CPU
,"[tid:%i] Removing thread context from CPU.\n", tid
);
880 // Copy Thread Data From RegFile
881 // If thread is suspended, it might be re-allocated
882 // this->copyToTC(tid);
885 // @todo: 2-27-2008: Fix how we free up rename mappings
886 // here to alleviate the case for double-freeing registers
889 // Unbind Int Regs from Rename Map
890 for (RegId
reg_id(IntRegClass
, 0); reg_id
.index() < TheISA::NumIntRegs
;
892 PhysRegIdPtr phys_reg
= renameMap
[tid
].lookup(reg_id
);
893 scoreboard
.unsetReg(phys_reg
);
894 freeList
.addReg(phys_reg
);
897 // Unbind Float Regs from Rename Map
898 for (RegId
reg_id(FloatRegClass
, 0); reg_id
.index() < TheISA::NumFloatRegs
;
900 PhysRegIdPtr phys_reg
= renameMap
[tid
].lookup(reg_id
);
901 scoreboard
.unsetReg(phys_reg
);
902 freeList
.addReg(phys_reg
);
905 // Unbind Float Regs from Rename Map
906 for (unsigned preg
= 0; preg
< TheISA::NumVecPredRegs
; preg
++) {
907 PhysRegIdPtr phys_reg
= renameMap
[tid
].lookup(
908 RegId(VecPredRegClass
, preg
));
909 scoreboard
.unsetReg(phys_reg
);
910 freeList
.addReg(phys_reg
);
913 // Unbind condition-code Regs from Rename Map
914 for (RegId
reg_id(CCRegClass
, 0); reg_id
.index() < TheISA::NumCCRegs
;
916 PhysRegIdPtr phys_reg
= renameMap
[tid
].lookup(reg_id
);
917 scoreboard
.unsetReg(phys_reg
);
918 freeList
.addReg(phys_reg
);
921 // Squash Throughout Pipeline
922 DynInstPtr inst
= commit
.rob
->readHeadInst(tid
);
923 InstSeqNum squash_seq_num
= inst
->seqNum
;
924 fetch
.squash(0, squash_seq_num
, inst
, tid
);
926 rename
.squash(squash_seq_num
, tid
);
928 iew
.ldstQueue
.squash(squash_seq_num
, tid
);
929 commit
.rob
->squash(squash_seq_num
, tid
);
932 assert(iew
.instQueue
.getCount(tid
) == 0);
933 assert(iew
.ldstQueue
.getCount(tid
) == 0);
935 // Reset ROB/IQ/LSQ Entries
937 // Commented out for now. This should be possible to do by
938 // telling all the pipeline stages to drain first, and then
939 // checking until the drain completes. Once the pipeline is
940 // drained, call resetEntries(). - 10-09-06 ktlim
942 if (activeThreads.size() >= 1) {
943 commit.rob->resetEntries();
949 template <class Impl
>
951 FullO3CPU
<Impl
>::hwrei(ThreadID tid
)
953 #if THE_ISA == ALPHA_ISA
954 // Need to clear the lock flag upon returning from an interrupt.
955 this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG
, false, tid
);
957 this->thread
[tid
]->kernelStats
->hwrei();
959 // FIXME: XXX check for interrupts? XXX
964 template <class Impl
>
966 FullO3CPU
<Impl
>::simPalCheck(int palFunc
, ThreadID tid
)
968 #if THE_ISA == ALPHA_ISA
969 if (this->thread
[tid
]->kernelStats
)
970 this->thread
[tid
]->kernelStats
->callpal(palFunc
,
971 this->threadContexts
[tid
]);
976 if (--System::numSystemsRunning
== 0)
977 exitSimLoop("all cpus halted");
982 if (this->system
->breakpoint())
990 template <class Impl
>
992 FullO3CPU
<Impl
>::switchRenameMode(ThreadID tid
, UnifiedFreeList
* freelist
)
994 auto pc
= this->pcState(tid
);
996 // new_mode is the new vector renaming mode
997 auto new_mode
= RenameMode
<TheISA::ISA
>::mode(pc
);
999 // We update vecMode only if there has been a change
1000 if (new_mode
!= vecMode
) {
1003 renameMap
[tid
].switchMode(vecMode
);
1004 commitRenameMap
[tid
].switchMode(vecMode
);
1005 renameMap
[tid
].switchFreeList(freelist
);
1009 template <class Impl
>
1011 FullO3CPU
<Impl
>::getInterrupts()
1013 // Check if there are any outstanding interrupts
1014 return this->interrupts
[0]->getInterrupt(this->threadContexts
[0]);
1017 template <class Impl
>
1019 FullO3CPU
<Impl
>::processInterrupts(const Fault
&interrupt
)
1021 // Check for interrupts here. For now can copy the code that
1022 // exists within isa_fullsys_traits.hh. Also assume that thread 0
1023 // is the one that handles the interrupts.
1024 // @todo: Possibly consolidate the interrupt checking code.
1025 // @todo: Allow other threads to handle interrupts.
1027 assert(interrupt
!= NoFault
);
1028 this->interrupts
[0]->updateIntrInfo(this->threadContexts
[0]);
1030 DPRINTF(O3CPU
, "Interrupt %s being handled\n", interrupt
->name());
1031 this->trap(interrupt
, 0, nullptr);
1034 template <class Impl
>
1036 FullO3CPU
<Impl
>::trap(const Fault
&fault
, ThreadID tid
,
1037 const StaticInstPtr
&inst
)
1039 // Pass the thread's TC into the invoke method.
1040 fault
->invoke(this->threadContexts
[tid
], inst
);
1043 template <class Impl
>
1045 FullO3CPU
<Impl
>::syscall(int64_t callnum
, ThreadID tid
, Fault
*fault
)
1047 DPRINTF(O3CPU
, "[tid:%i] Executing syscall().\n\n", tid
);
1049 DPRINTF(Activity
,"Activity: syscall() called.\n");
1051 // Temporarily increase this by one to account for the syscall
1053 ++(this->thread
[tid
]->funcExeInst
);
1055 // Execute the actual syscall.
1056 this->thread
[tid
]->syscall(callnum
, fault
);
1058 // Decrease funcExeInst by one as the normal commit will handle
1060 --(this->thread
[tid
]->funcExeInst
);
1063 template <class Impl
>
1065 FullO3CPU
<Impl
>::serializeThread(CheckpointOut
&cp
, ThreadID tid
) const
1067 thread
[tid
]->serialize(cp
);
1070 template <class Impl
>
1072 FullO3CPU
<Impl
>::unserializeThread(CheckpointIn
&cp
, ThreadID tid
)
1074 thread
[tid
]->unserialize(cp
);
1077 template <class Impl
>
1079 FullO3CPU
<Impl
>::drain()
1081 // Deschedule any power gating event (if any)
1082 deschedulePowerGatingEvent();
1084 // If the CPU isn't doing anything, then return immediately.
1086 return DrainState::Drained
;
1088 DPRINTF(Drain
, "Draining...\n");
1090 // We only need to signal a drain to the commit stage as this
1091 // initiates squashing controls the draining. Once the commit
1092 // stage commits an instruction where it is safe to stop, it'll
1093 // squash the rest of the instructions in the pipeline and force
1094 // the fetch stage to stall. The pipeline will be drained once all
1095 // in-flight instructions have retired.
1098 // Wake the CPU and record activity so everything can drain out if
1099 // the CPU was not able to immediately drain.
1101 // If a thread is suspended, wake it up so it can be drained
1102 for (auto t
: threadContexts
) {
1103 if (t
->status() == ThreadContext::Suspended
){
1104 DPRINTF(Drain
, "Currently suspended so activate %i \n",
1107 // As the thread is now active, change the power state as well
1108 activateContext(t
->threadId());
1113 activityRec
.activity();
1115 DPRINTF(Drain
, "CPU not drained\n");
1117 return DrainState::Draining
;
1119 DPRINTF(Drain
, "CPU is already drained\n");
1120 if (tickEvent
.scheduled())
1121 deschedule(tickEvent
);
1123 // Flush out any old data from the time buffers. In
1124 // particular, there might be some data in flight from the
1125 // fetch stage that isn't visible in any of the CPU buffers we
1126 // test in isDrained().
1127 for (int i
= 0; i
< timeBuffer
.getSize(); ++i
) {
1128 timeBuffer
.advance();
1129 fetchQueue
.advance();
1130 decodeQueue
.advance();
1131 renameQueue
.advance();
1136 return DrainState::Drained
;
1140 template <class Impl
>
1142 FullO3CPU
<Impl
>::tryDrain()
1144 if (drainState() != DrainState::Draining
|| !isDrained())
1147 if (tickEvent
.scheduled())
1148 deschedule(tickEvent
);
1150 DPRINTF(Drain
, "CPU done draining, processing drain event\n");
1156 template <class Impl
>
1158 FullO3CPU
<Impl
>::drainSanityCheck() const
1160 assert(isDrained());
1161 fetch
.drainSanityCheck();
1162 decode
.drainSanityCheck();
1163 rename
.drainSanityCheck();
1164 iew
.drainSanityCheck();
1165 commit
.drainSanityCheck();
1168 template <class Impl
>
1170 FullO3CPU
<Impl
>::isDrained() const
1174 if (!instList
.empty() || !removeList
.empty()) {
1175 DPRINTF(Drain
, "Main CPU structures not drained.\n");
1179 if (!fetch
.isDrained()) {
1180 DPRINTF(Drain
, "Fetch not drained.\n");
1184 if (!decode
.isDrained()) {
1185 DPRINTF(Drain
, "Decode not drained.\n");
1189 if (!rename
.isDrained()) {
1190 DPRINTF(Drain
, "Rename not drained.\n");
1194 if (!iew
.isDrained()) {
1195 DPRINTF(Drain
, "IEW not drained.\n");
1199 if (!commit
.isDrained()) {
1200 DPRINTF(Drain
, "Commit not drained.\n");
1207 template <class Impl
>
1209 FullO3CPU
<Impl
>::commitDrained(ThreadID tid
)
1211 fetch
.drainStall(tid
);
1214 template <class Impl
>
1216 FullO3CPU
<Impl
>::drainResume()
1221 DPRINTF(Drain
, "Resuming...\n");
1224 fetch
.drainResume();
1225 commit
.drainResume();
1228 for (ThreadID i
= 0; i
< thread
.size(); i
++) {
1229 if (thread
[i
]->status() == ThreadContext::Active
) {
1230 DPRINTF(Drain
, "Activating thread: %i\n", i
);
1236 assert(!tickEvent
.scheduled());
1237 if (_status
== Running
)
1238 schedule(tickEvent
, nextCycle());
1240 // Reschedule any power gating event (if any)
1241 schedulePowerGatingEvent();
1244 template <class Impl
>
1246 FullO3CPU
<Impl
>::switchOut()
1248 DPRINTF(O3CPU
, "Switching out\n");
1249 BaseCPU::switchOut();
1251 activityRec
.reset();
1253 _status
= SwitchedOut
;
1256 checker
->switchOut();
1259 template <class Impl
>
1261 FullO3CPU
<Impl
>::takeOverFrom(BaseCPU
*oldCPU
)
1263 BaseCPU::takeOverFrom(oldCPU
);
1265 fetch
.takeOverFrom();
1266 decode
.takeOverFrom();
1267 rename
.takeOverFrom();
1269 commit
.takeOverFrom();
1271 assert(!tickEvent
.scheduled());
1273 FullO3CPU
<Impl
> *oldO3CPU
= dynamic_cast<FullO3CPU
<Impl
>*>(oldCPU
);
1275 globalSeqNum
= oldO3CPU
->globalSeqNum
;
1277 lastRunningCycle
= curCycle();
1281 template <class Impl
>
1283 FullO3CPU
<Impl
>::verifyMemoryMode() const
1285 if (!system
->isTimingMode()) {
1286 fatal("The O3 CPU requires the memory system to be in "
1287 "'timing' mode.\n");
1291 template <class Impl
>
1293 FullO3CPU
<Impl
>::readMiscRegNoEffect(int misc_reg
, ThreadID tid
) const
1295 return this->isa
[tid
]->readMiscRegNoEffect(misc_reg
);
1298 template <class Impl
>
1300 FullO3CPU
<Impl
>::readMiscReg(int misc_reg
, ThreadID tid
)
1303 return this->isa
[tid
]->readMiscReg(misc_reg
, tcBase(tid
));
1306 template <class Impl
>
1308 FullO3CPU
<Impl
>::setMiscRegNoEffect(int misc_reg
, RegVal val
, ThreadID tid
)
1310 this->isa
[tid
]->setMiscRegNoEffect(misc_reg
, val
);
1313 template <class Impl
>
1315 FullO3CPU
<Impl
>::setMiscReg(int misc_reg
, RegVal val
, ThreadID tid
)
1317 miscRegfileWrites
++;
1318 this->isa
[tid
]->setMiscReg(misc_reg
, val
, tcBase(tid
));
1321 template <class Impl
>
1323 FullO3CPU
<Impl
>::readIntReg(PhysRegIdPtr phys_reg
)
1326 return regFile
.readIntReg(phys_reg
);
1329 template <class Impl
>
1331 FullO3CPU
<Impl
>::readFloatRegBits(PhysRegIdPtr phys_reg
)
1334 return regFile
.readFloatRegBits(phys_reg
);
1337 template <class Impl
>
1339 FullO3CPU
<Impl
>::readVecReg(PhysRegIdPtr phys_reg
) const
1340 -> const VecRegContainer
&
1343 return regFile
.readVecReg(phys_reg
);
1346 template <class Impl
>
1348 FullO3CPU
<Impl
>::getWritableVecReg(PhysRegIdPtr phys_reg
)
1352 return regFile
.getWritableVecReg(phys_reg
);
1355 template <class Impl
>
1357 FullO3CPU
<Impl
>::readVecElem(PhysRegIdPtr phys_reg
) const -> const VecElem
&
1360 return regFile
.readVecElem(phys_reg
);
1363 template <class Impl
>
1365 FullO3CPU
<Impl
>::readVecPredReg(PhysRegIdPtr phys_reg
) const
1366 -> const VecPredRegContainer
&
1368 vecPredRegfileReads
++;
1369 return regFile
.readVecPredReg(phys_reg
);
1372 template <class Impl
>
1374 FullO3CPU
<Impl
>::getWritableVecPredReg(PhysRegIdPtr phys_reg
)
1375 -> VecPredRegContainer
&
1377 vecPredRegfileWrites
++;
1378 return regFile
.getWritableVecPredReg(phys_reg
);
1381 template <class Impl
>
1383 FullO3CPU
<Impl
>::readCCReg(PhysRegIdPtr phys_reg
)
1386 return regFile
.readCCReg(phys_reg
);
1389 template <class Impl
>
1391 FullO3CPU
<Impl
>::setIntReg(PhysRegIdPtr phys_reg
, RegVal val
)
1394 regFile
.setIntReg(phys_reg
, val
);
1397 template <class Impl
>
1399 FullO3CPU
<Impl
>::setFloatRegBits(PhysRegIdPtr phys_reg
, RegVal val
)
1402 regFile
.setFloatRegBits(phys_reg
, val
);
1405 template <class Impl
>
1407 FullO3CPU
<Impl
>::setVecReg(PhysRegIdPtr phys_reg
, const VecRegContainer
& val
)
1410 regFile
.setVecReg(phys_reg
, val
);
1413 template <class Impl
>
1415 FullO3CPU
<Impl
>::setVecElem(PhysRegIdPtr phys_reg
, const VecElem
& val
)
1418 regFile
.setVecElem(phys_reg
, val
);
1421 template <class Impl
>
1423 FullO3CPU
<Impl
>::setVecPredReg(PhysRegIdPtr phys_reg
,
1424 const VecPredRegContainer
& val
)
1426 vecPredRegfileWrites
++;
1427 regFile
.setVecPredReg(phys_reg
, val
);
1430 template <class Impl
>
1432 FullO3CPU
<Impl
>::setCCReg(PhysRegIdPtr phys_reg
, CCReg val
)
1435 regFile
.setCCReg(phys_reg
, val
);
1438 template <class Impl
>
1440 FullO3CPU
<Impl
>::readArchIntReg(int reg_idx
, ThreadID tid
)
1443 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1444 RegId(IntRegClass
, reg_idx
));
1446 return regFile
.readIntReg(phys_reg
);
1449 template <class Impl
>
1451 FullO3CPU
<Impl
>::readArchFloatRegBits(int reg_idx
, ThreadID tid
)
1454 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1455 RegId(FloatRegClass
, reg_idx
));
1457 return regFile
.readFloatRegBits(phys_reg
);
1460 template <class Impl
>
1462 FullO3CPU
<Impl
>::readArchVecReg(int reg_idx
, ThreadID tid
) const
1463 -> const VecRegContainer
&
1465 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1466 RegId(VecRegClass
, reg_idx
));
1467 return readVecReg(phys_reg
);
1470 template <class Impl
>
1472 FullO3CPU
<Impl
>::getWritableArchVecReg(int reg_idx
, ThreadID tid
)
1475 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1476 RegId(VecRegClass
, reg_idx
));
1477 return getWritableVecReg(phys_reg
);
1480 template <class Impl
>
1482 FullO3CPU
<Impl
>::readArchVecElem(const RegIndex
& reg_idx
, const ElemIndex
& ldx
,
1483 ThreadID tid
) const -> const VecElem
&
1485 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1486 RegId(VecElemClass
, reg_idx
, ldx
));
1487 return readVecElem(phys_reg
);
1490 template <class Impl
>
1492 FullO3CPU
<Impl
>::readArchVecPredReg(int reg_idx
, ThreadID tid
) const
1493 -> const VecPredRegContainer
&
1495 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1496 RegId(VecPredRegClass
, reg_idx
));
1497 return readVecPredReg(phys_reg
);
1500 template <class Impl
>
1502 FullO3CPU
<Impl
>::getWritableArchVecPredReg(int reg_idx
, ThreadID tid
)
1503 -> VecPredRegContainer
&
1505 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1506 RegId(VecPredRegClass
, reg_idx
));
1507 return getWritableVecPredReg(phys_reg
);
1510 template <class Impl
>
1512 FullO3CPU
<Impl
>::readArchCCReg(int reg_idx
, ThreadID tid
)
1515 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1516 RegId(CCRegClass
, reg_idx
));
1518 return regFile
.readCCReg(phys_reg
);
1521 template <class Impl
>
1523 FullO3CPU
<Impl
>::setArchIntReg(int reg_idx
, RegVal val
, ThreadID tid
)
1526 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1527 RegId(IntRegClass
, reg_idx
));
1529 regFile
.setIntReg(phys_reg
, val
);
1532 template <class Impl
>
1534 FullO3CPU
<Impl
>::setArchFloatRegBits(int reg_idx
, RegVal val
, ThreadID tid
)
1537 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1538 RegId(FloatRegClass
, reg_idx
));
1540 regFile
.setFloatRegBits(phys_reg
, val
);
1543 template <class Impl
>
1545 FullO3CPU
<Impl
>::setArchVecReg(int reg_idx
, const VecRegContainer
& val
,
1548 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1549 RegId(VecRegClass
, reg_idx
));
1550 setVecReg(phys_reg
, val
);
1553 template <class Impl
>
1555 FullO3CPU
<Impl
>::setArchVecElem(const RegIndex
& reg_idx
, const ElemIndex
& ldx
,
1556 const VecElem
& val
, ThreadID tid
)
1558 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1559 RegId(VecElemClass
, reg_idx
, ldx
));
1560 setVecElem(phys_reg
, val
);
1563 template <class Impl
>
1565 FullO3CPU
<Impl
>::setArchVecPredReg(int reg_idx
, const VecPredRegContainer
& val
,
1568 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1569 RegId(VecPredRegClass
, reg_idx
));
1570 setVecPredReg(phys_reg
, val
);
1573 template <class Impl
>
1575 FullO3CPU
<Impl
>::setArchCCReg(int reg_idx
, CCReg val
, ThreadID tid
)
1578 PhysRegIdPtr phys_reg
= commitRenameMap
[tid
].lookup(
1579 RegId(CCRegClass
, reg_idx
));
1581 regFile
.setCCReg(phys_reg
, val
);
1584 template <class Impl
>
1586 FullO3CPU
<Impl
>::pcState(ThreadID tid
)
1588 return commit
.pcState(tid
);
1591 template <class Impl
>
1593 FullO3CPU
<Impl
>::pcState(const TheISA::PCState
&val
, ThreadID tid
)
1595 commit
.pcState(val
, tid
);
1598 template <class Impl
>
1600 FullO3CPU
<Impl
>::instAddr(ThreadID tid
)
1602 return commit
.instAddr(tid
);
1605 template <class Impl
>
1607 FullO3CPU
<Impl
>::nextInstAddr(ThreadID tid
)
1609 return commit
.nextInstAddr(tid
);
1612 template <class Impl
>
1614 FullO3CPU
<Impl
>::microPC(ThreadID tid
)
1616 return commit
.microPC(tid
);
1619 template <class Impl
>
1621 FullO3CPU
<Impl
>::squashFromTC(ThreadID tid
)
1623 this->thread
[tid
]->noSquashFromTC
= true;
1624 this->commit
.generateTCEvent(tid
);
1627 template <class Impl
>
1628 typename FullO3CPU
<Impl
>::ListIt
1629 FullO3CPU
<Impl
>::addInst(const DynInstPtr
&inst
)
1631 instList
.push_back(inst
);
1633 return --(instList
.end());
1636 template <class Impl
>
1638 FullO3CPU
<Impl
>::instDone(ThreadID tid
, const DynInstPtr
&inst
)
1640 // Keep an instruction count.
1641 if (!inst
->isMicroop() || inst
->isLastMicroop()) {
1642 thread
[tid
]->numInst
++;
1643 thread
[tid
]->numInsts
++;
1644 committedInsts
[tid
]++;
1645 system
->totalNumInsts
++;
1647 // Check for instruction-count-based events.
1648 comInstEventQueue
[tid
]->serviceEvents(thread
[tid
]->numInst
);
1649 system
->instEventQueue
.serviceEvents(system
->totalNumInsts
);
1651 thread
[tid
]->numOp
++;
1652 thread
[tid
]->numOps
++;
1653 committedOps
[tid
]++;
1655 probeInstCommit(inst
->staticInst
);
1658 template <class Impl
>
1660 FullO3CPU
<Impl
>::removeFrontInst(const DynInstPtr
&inst
)
1662 DPRINTF(O3CPU
, "Removing committed instruction [tid:%i] PC %s "
1664 inst
->threadNumber
, inst
->pcState(), inst
->seqNum
);
1666 removeInstsThisCycle
= true;
1668 // Remove the front instruction.
1669 removeList
.push(inst
->getInstListIt());
1672 template <class Impl
>
1674 FullO3CPU
<Impl
>::removeInstsNotInROB(ThreadID tid
)
1676 DPRINTF(O3CPU
, "Thread %i: Deleting instructions from instruction"
1681 bool rob_empty
= false;
1683 if (instList
.empty()) {
1685 } else if (rob
.isEmpty(tid
)) {
1686 DPRINTF(O3CPU
, "ROB is empty, squashing all insts.\n");
1687 end_it
= instList
.begin();
1690 end_it
= (rob
.readTailInst(tid
))->getInstListIt();
1691 DPRINTF(O3CPU
, "ROB is not empty, squashing insts not in ROB.\n");
1694 removeInstsThisCycle
= true;
1696 ListIt inst_it
= instList
.end();
1700 // Walk through the instruction list, removing any instructions
1701 // that were inserted after the given instruction iterator, end_it.
1702 while (inst_it
!= end_it
) {
1703 assert(!instList
.empty());
1705 squashInstIt(inst_it
, tid
);
1710 // If the ROB was empty, then we actually need to remove the first
1711 // instruction as well.
1713 squashInstIt(inst_it
, tid
);
1717 template <class Impl
>
1719 FullO3CPU
<Impl
>::removeInstsUntil(const InstSeqNum
&seq_num
, ThreadID tid
)
1721 assert(!instList
.empty());
1723 removeInstsThisCycle
= true;
1725 ListIt inst_iter
= instList
.end();
1729 DPRINTF(O3CPU
, "Deleting instructions from instruction "
1730 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1731 tid
, seq_num
, (*inst_iter
)->seqNum
);
1733 while ((*inst_iter
)->seqNum
> seq_num
) {
1735 bool break_loop
= (inst_iter
== instList
.begin());
1737 squashInstIt(inst_iter
, tid
);
1746 template <class Impl
>
1748 FullO3CPU
<Impl
>::squashInstIt(const ListIt
&instIt
, ThreadID tid
)
1750 if ((*instIt
)->threadNumber
== tid
) {
1751 DPRINTF(O3CPU
, "Squashing instruction, "
1752 "[tid:%i] [sn:%lli] PC %s\n",
1753 (*instIt
)->threadNumber
,
1755 (*instIt
)->pcState());
1757 // Mark it as squashed.
1758 (*instIt
)->setSquashed();
1760 // @todo: Formulate a consistent method for deleting
1761 // instructions from the instruction list
1762 // Remove the instruction from the list.
1763 removeList
.push(instIt
);
1767 template <class Impl
>
1769 FullO3CPU
<Impl
>::cleanUpRemovedInsts()
1771 while (!removeList
.empty()) {
1772 DPRINTF(O3CPU
, "Removing instruction, "
1773 "[tid:%i] [sn:%lli] PC %s\n",
1774 (*removeList
.front())->threadNumber
,
1775 (*removeList
.front())->seqNum
,
1776 (*removeList
.front())->pcState());
1778 instList
.erase(removeList
.front());
1783 removeInstsThisCycle
= false;
1786 template <class Impl>
1788 FullO3CPU<Impl>::removeAllInsts()
1793 template <class Impl
>
1795 FullO3CPU
<Impl
>::dumpInsts()
1799 ListIt inst_list_it
= instList
.begin();
1801 cprintf("Dumping Instruction List\n");
1803 while (inst_list_it
!= instList
.end()) {
1804 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1806 num
, (*inst_list_it
)->instAddr(), (*inst_list_it
)->threadNumber
,
1807 (*inst_list_it
)->seqNum
, (*inst_list_it
)->isIssued(),
1808 (*inst_list_it
)->isSquashed());
1814 template <class Impl>
1816 FullO3CPU<Impl>::wakeDependents(const DynInstPtr &inst)
1818 iew.wakeDependents(inst);
1821 template <class Impl
>
1823 FullO3CPU
<Impl
>::wakeCPU()
1825 if (activityRec
.active() || tickEvent
.scheduled()) {
1826 DPRINTF(Activity
, "CPU already running.\n");
1830 DPRINTF(Activity
, "Waking up CPU\n");
1832 Cycles
cycles(curCycle() - lastRunningCycle
);
1833 // @todo: This is an oddity that is only here to match the stats
1836 idleCycles
+= cycles
;
1837 numCycles
+= cycles
;
1840 schedule(tickEvent
, clockEdge());
1843 template <class Impl
>
1845 FullO3CPU
<Impl
>::wakeup(ThreadID tid
)
1847 if (this->thread
[tid
]->status() != ThreadContext::Suspended
)
1852 DPRINTF(Quiesce
, "Suspended Processor woken\n");
1853 this->threadContexts
[tid
]->activate();
1856 template <class Impl
>
1858 FullO3CPU
<Impl
>::getFreeTid()
1860 for (ThreadID tid
= 0; tid
< numThreads
; tid
++) {
1867 return InvalidThreadID
;
1870 template <class Impl
>
1872 FullO3CPU
<Impl
>::updateThreadPriority()
1874 if (activeThreads
.size() > 1) {
1875 //DEFAULT TO ROUND ROBIN SCHEME
1876 //e.g. Move highest priority to end of thread list
1877 list
<ThreadID
>::iterator list_begin
= activeThreads
.begin();
1879 unsigned high_thread
= *list_begin
;
1881 activeThreads
.erase(list_begin
);
1883 activeThreads
.push_back(high_thread
);
1887 // Forward declaration of FullO3CPU.
1888 template class FullO3CPU
<O3CPUImpl
>;