cpu.cc (10225:01df075d9f93) cpu.cc (10239:592f0bb6bd6f)
1/*
2 * Copyright (c) 2011-2012 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
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.
14 *
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.
18 *
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.
29 *
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.
41 *
42 * Authors: Kevin Lim
43 * Korey Sewell
44 * Rick Strong
45 */
46
47#include "arch/kernel_stats.hh"
48#include "config/the_isa.hh"
49#include "cpu/checker/cpu.hh"
50#include "cpu/checker/thread_context.hh"
51#include "cpu/o3/cpu.hh"
52#include "cpu/o3/isa_specific.hh"
53#include "cpu/o3/thread_context.hh"
54#include "cpu/activity.hh"
55#include "cpu/quiesce_event.hh"
56#include "cpu/simple_thread.hh"
57#include "cpu/thread_context.hh"
58#include "debug/Activity.hh"
59#include "debug/Drain.hh"
60#include "debug/O3CPU.hh"
61#include "debug/Quiesce.hh"
62#include "enums/MemoryMode.hh"
63#include "sim/core.hh"
64#include "sim/full_system.hh"
65#include "sim/process.hh"
66#include "sim/stat_control.hh"
67#include "sim/system.hh"
68
69#if THE_ISA == ALPHA_ISA
70#include "arch/alpha/osfpal.hh"
71#include "debug/Activity.hh"
72#endif
73
74struct BaseCPUParams;
75
76using namespace TheISA;
77using namespace std;
78
79BaseO3CPU::BaseO3CPU(BaseCPUParams *params)
80 : BaseCPU(params)
81{
82}
83
84void
85BaseO3CPU::regStats()
86{
87 BaseCPU::regStats();
88}
89
90template<class Impl>
91bool
92FullO3CPU<Impl>::IcachePort::recvTimingResp(PacketPtr pkt)
93{
94 DPRINTF(O3CPU, "Fetch unit received timing\n");
95 // We shouldn't ever get a block in ownership state
96 assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted()));
97 fetch->processCacheCompletion(pkt);
98
99 return true;
100}
101
102template<class Impl>
103void
104FullO3CPU<Impl>::IcachePort::recvRetry()
105{
106 fetch->recvRetry();
107}
108
109template <class Impl>
110bool
111FullO3CPU<Impl>::DcachePort::recvTimingResp(PacketPtr pkt)
112{
113 return lsq->recvTimingResp(pkt);
114}
115
116template <class Impl>
117void
118FullO3CPU<Impl>::DcachePort::recvTimingSnoopReq(PacketPtr pkt)
119{
120 lsq->recvTimingSnoopReq(pkt);
121}
122
123template <class Impl>
124void
125FullO3CPU<Impl>::DcachePort::recvRetry()
126{
127 lsq->recvRetry();
128}
129
130template <class Impl>
131FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
132 : Event(CPU_Tick_Pri), cpu(c)
133{
134}
135
136template <class Impl>
137void
138FullO3CPU<Impl>::TickEvent::process()
139{
140 cpu->tick();
141}
142
143template <class Impl>
144const char *
145FullO3CPU<Impl>::TickEvent::description() const
146{
147 return "FullO3CPU tick";
148}
149
150template <class Impl>
151FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent()
152 : Event(CPU_Switch_Pri)
153{
154}
155
156template <class Impl>
157void
158FullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num,
159 FullO3CPU<Impl> *thread_cpu)
160{
161 tid = thread_num;
162 cpu = thread_cpu;
163}
164
165template <class Impl>
166void
167FullO3CPU<Impl>::ActivateThreadEvent::process()
168{
169 cpu->activateThread(tid);
170}
171
172template <class Impl>
173const char *
174FullO3CPU<Impl>::ActivateThreadEvent::description() const
175{
176 return "FullO3CPU \"Activate Thread\"";
177}
178
179template <class Impl>
180FullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent()
181 : Event(CPU_Tick_Pri), tid(0), remove(false), cpu(NULL)
182{
183}
184
185template <class Impl>
186void
187FullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num,
188 FullO3CPU<Impl> *thread_cpu)
189{
190 tid = thread_num;
191 cpu = thread_cpu;
192 remove = false;
193}
194
195template <class Impl>
196void
197FullO3CPU<Impl>::DeallocateContextEvent::process()
198{
199 cpu->deactivateThread(tid);
200 if (remove)
201 cpu->removeThread(tid);
202}
203
204template <class Impl>
205const char *
206FullO3CPU<Impl>::DeallocateContextEvent::description() const
207{
208 return "FullO3CPU \"Deallocate Context\"";
209}
210
211template <class Impl>
212FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
213 : BaseO3CPU(params),
214 itb(params->itb),
215 dtb(params->dtb),
216 tickEvent(this),
217#ifndef NDEBUG
218 instcount(0),
219#endif
220 removeInstsThisCycle(false),
221 fetch(this, params),
222 decode(this, params),
223 rename(this, params),
224 iew(this, params),
225 commit(this, params),
226
227 regFile(params->numPhysIntRegs,
228 params->numPhysFloatRegs,
229 params->numPhysCCRegs),
230
231 freeList(name() + ".freelist", &regFile),
232
233 rob(this, params),
234
235 scoreboard(name() + ".scoreboard",
236 regFile.totalNumPhysRegs(), TheISA::NumMiscRegs,
237 TheISA::ZeroReg, TheISA::ZeroReg),
238
239 isa(numThreads, NULL),
240
241 icachePort(&fetch, this),
242 dcachePort(&iew.ldstQueue, this),
243
244 timeBuffer(params->backComSize, params->forwardComSize),
245 fetchQueue(params->backComSize, params->forwardComSize),
246 decodeQueue(params->backComSize, params->forwardComSize),
247 renameQueue(params->backComSize, params->forwardComSize),
248 iewQueue(params->backComSize, params->forwardComSize),
249 activityRec(name(), NumStages,
250 params->backComSize + params->forwardComSize,
251 params->activity),
252
253 globalSeqNum(1),
254 system(params->system),
255 drainManager(NULL),
256 lastRunningCycle(curCycle())
257{
258 if (!params->switched_out) {
259 _status = Running;
260 } else {
261 _status = SwitchedOut;
262 }
263
264 if (params->checker) {
265 BaseCPU *temp_checker = params->checker;
266 checker = dynamic_cast<Checker<Impl> *>(temp_checker);
267 checker->setIcachePort(&icachePort);
268 checker->setSystem(params->system);
269 } else {
270 checker = NULL;
271 }
272
273 if (!FullSystem) {
274 thread.resize(numThreads);
275 tids.resize(numThreads);
276 }
277
278 // The stages also need their CPU pointer setup. However this
279 // must be done at the upper level CPU because they have pointers
280 // to the upper level CPU, and not this FullO3CPU.
281
282 // Set up Pointers to the activeThreads list for each stage
283 fetch.setActiveThreads(&activeThreads);
284 decode.setActiveThreads(&activeThreads);
285 rename.setActiveThreads(&activeThreads);
286 iew.setActiveThreads(&activeThreads);
287 commit.setActiveThreads(&activeThreads);
288
289 // Give each of the stages the time buffer they will use.
290 fetch.setTimeBuffer(&timeBuffer);
291 decode.setTimeBuffer(&timeBuffer);
292 rename.setTimeBuffer(&timeBuffer);
293 iew.setTimeBuffer(&timeBuffer);
294 commit.setTimeBuffer(&timeBuffer);
295
296 // Also setup each of the stages' queues.
297 fetch.setFetchQueue(&fetchQueue);
298 decode.setFetchQueue(&fetchQueue);
299 commit.setFetchQueue(&fetchQueue);
300 decode.setDecodeQueue(&decodeQueue);
301 rename.setDecodeQueue(&decodeQueue);
302 rename.setRenameQueue(&renameQueue);
303 iew.setRenameQueue(&renameQueue);
304 iew.setIEWQueue(&iewQueue);
305 commit.setIEWQueue(&iewQueue);
306 commit.setRenameQueue(&renameQueue);
307
308 commit.setIEWStage(&iew);
309 rename.setIEWStage(&iew);
310 rename.setCommitStage(&commit);
311
312 ThreadID active_threads;
313 if (FullSystem) {
314 active_threads = 1;
315 } else {
316 active_threads = params->workload.size();
317
318 if (active_threads > Impl::MaxThreads) {
319 panic("Workload Size too large. Increase the 'MaxThreads' "
320 "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) "
321 "or edit your workload size.");
322 }
323 }
324
325 //Make Sure That this a Valid Architeture
326 assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs);
327 assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
328 assert(params->numPhysCCRegs >= numThreads * TheISA::NumCCRegs);
329
330 rename.setScoreboard(&scoreboard);
331 iew.setScoreboard(&scoreboard);
332
333 // Setup the rename map for whichever stages need it.
334 for (ThreadID tid = 0; tid < numThreads; tid++) {
335 isa[tid] = params->isa[tid];
336
337 // Only Alpha has an FP zero register, so for other ISAs we
338 // use an invalid FP register index to avoid special treatment
339 // of any valid FP reg.
340 RegIndex invalidFPReg = TheISA::NumFloatRegs + 1;
341 RegIndex fpZeroReg =
342 (THE_ISA == ALPHA_ISA) ? TheISA::ZeroReg : invalidFPReg;
343
344 commitRenameMap[tid].init(&regFile, TheISA::ZeroReg, fpZeroReg,
345 &freeList);
346
347 renameMap[tid].init(&regFile, TheISA::ZeroReg, fpZeroReg,
348 &freeList);
349
350 activateThreadEvent[tid].init(tid, this);
351 deallocateContextEvent[tid].init(tid, this);
352 }
353
354 // Initialize rename map to assign physical registers to the
355 // architectural registers for active threads only.
356 for (ThreadID tid = 0; tid < active_threads; tid++) {
357 for (RegIndex ridx = 0; ridx < TheISA::NumIntRegs; ++ridx) {
358 // Note that we can't use the rename() method because we don't
359 // want special treatment for the zero register at this point
360 PhysRegIndex phys_reg = freeList.getIntReg();
361 renameMap[tid].setIntEntry(ridx, phys_reg);
362 commitRenameMap[tid].setIntEntry(ridx, phys_reg);
363 }
364
365 for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) {
366 PhysRegIndex phys_reg = freeList.getFloatReg();
367 renameMap[tid].setFloatEntry(ridx, phys_reg);
368 commitRenameMap[tid].setFloatEntry(ridx, phys_reg);
369 }
370
371 for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) {
372 PhysRegIndex phys_reg = freeList.getCCReg();
373 renameMap[tid].setCCEntry(ridx, phys_reg);
374 commitRenameMap[tid].setCCEntry(ridx, phys_reg);
375 }
376 }
377
378 rename.setRenameMap(renameMap);
379 commit.setRenameMap(commitRenameMap);
380 rename.setFreeList(&freeList);
381
382 // Setup the ROB for whichever stages need it.
383 commit.setROB(&rob);
384
385 lastActivatedCycle = 0;
386#if 0
387 // Give renameMap & rename stage access to the freeList;
388 for (ThreadID tid = 0; tid < numThreads; tid++)
389 globalSeqNum[tid] = 1;
390#endif
391
392 contextSwitch = false;
393 DPRINTF(O3CPU, "Creating O3CPU object.\n");
394
395 // Setup any thread state.
396 this->thread.resize(this->numThreads);
397
398 for (ThreadID tid = 0; tid < this->numThreads; ++tid) {
399 if (FullSystem) {
400 // SMT is not supported in FS mode yet.
401 assert(this->numThreads == 1);
402 this->thread[tid] = new Thread(this, 0, NULL);
403 } else {
404 if (tid < params->workload.size()) {
405 DPRINTF(O3CPU, "Workload[%i] process is %#x",
406 tid, this->thread[tid]);
407 this->thread[tid] = new typename FullO3CPU<Impl>::Thread(
408 (typename Impl::O3CPU *)(this),
409 tid, params->workload[tid]);
410
411 //usedTids[tid] = true;
412 //threadMap[tid] = tid;
413 } else {
414 //Allocate Empty thread so M5 can use later
415 //when scheduling threads to CPU
416 Process* dummy_proc = NULL;
417
418 this->thread[tid] = new typename FullO3CPU<Impl>::Thread(
419 (typename Impl::O3CPU *)(this),
420 tid, dummy_proc);
421 //usedTids[tid] = false;
422 }
423 }
424
425 ThreadContext *tc;
426
427 // Setup the TC that will serve as the interface to the threads/CPU.
428 O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>;
429
430 tc = o3_tc;
431
432 // If we're using a checker, then the TC should be the
433 // CheckerThreadContext.
434 if (params->checker) {
435 tc = new CheckerThreadContext<O3ThreadContext<Impl> >(
436 o3_tc, this->checker);
437 }
438
439 o3_tc->cpu = (typename Impl::O3CPU *)(this);
440 assert(o3_tc->cpu);
441 o3_tc->thread = this->thread[tid];
442
443 if (FullSystem) {
444 // Setup quiesce event.
445 this->thread[tid]->quiesceEvent = new EndQuiesceEvent(tc);
446 }
447 // Give the thread the TC.
448 this->thread[tid]->tc = tc;
449
450 // Add the TC to the CPU's list of TC's.
451 this->threadContexts.push_back(tc);
452 }
453
454 // FullO3CPU always requires an interrupt controller.
455 if (!params->switched_out && !interrupts) {
456 fatal("FullO3CPU %s has no interrupt controller.\n"
457 "Ensure createInterruptController() is called.\n", name());
458 }
459
460 for (ThreadID tid = 0; tid < this->numThreads; tid++)
461 this->thread[tid]->setFuncExeInst(0);
462}
463
464template <class Impl>
465FullO3CPU<Impl>::~FullO3CPU()
466{
467}
468
469template <class Impl>
470void
471FullO3CPU<Impl>::regProbePoints()
472{
473 ppInstAccessComplete = new ProbePointArg<PacketPtr>(getProbeManager(), "InstAccessComplete");
474 ppDataAccessComplete = new ProbePointArg<std::pair<DynInstPtr, PacketPtr> >(getProbeManager(), "DataAccessComplete");
475 fetch.regProbePoints();
476 iew.regProbePoints();
477 commit.regProbePoints();
478}
479
480template <class Impl>
481void
482FullO3CPU<Impl>::regStats()
483{
484 BaseO3CPU::regStats();
485
486 // Register any of the O3CPU's stats here.
487 timesIdled
488 .name(name() + ".timesIdled")
489 .desc("Number of times that the entire CPU went into an idle state and"
490 " unscheduled itself")
491 .prereq(timesIdled);
492
493 idleCycles
494 .name(name() + ".idleCycles")
495 .desc("Total number of cycles that the CPU has spent unscheduled due "
496 "to idling")
497 .prereq(idleCycles);
498
499 quiesceCycles
500 .name(name() + ".quiesceCycles")
501 .desc("Total number of cycles that CPU has spent quiesced or waiting "
502 "for an interrupt")
503 .prereq(quiesceCycles);
504
505 // Number of Instructions simulated
506 // --------------------------------
507 // Should probably be in Base CPU but need templated
508 // MaxThreads so put in here instead
509 committedInsts
510 .init(numThreads)
511 .name(name() + ".committedInsts")
512 .desc("Number of Instructions Simulated")
513 .flags(Stats::total);
514
515 committedOps
516 .init(numThreads)
517 .name(name() + ".committedOps")
518 .desc("Number of Ops (including micro ops) Simulated")
519 .flags(Stats::total);
520
521 cpi
522 .name(name() + ".cpi")
523 .desc("CPI: Cycles Per Instruction")
524 .precision(6);
525 cpi = numCycles / committedInsts;
526
527 totalCpi
528 .name(name() + ".cpi_total")
529 .desc("CPI: Total CPI of All Threads")
530 .precision(6);
531 totalCpi = numCycles / sum(committedInsts);
532
533 ipc
534 .name(name() + ".ipc")
535 .desc("IPC: Instructions Per Cycle")
536 .precision(6);
537 ipc = committedInsts / numCycles;
538
539 totalIpc
540 .name(name() + ".ipc_total")
541 .desc("IPC: Total IPC of All Threads")
542 .precision(6);
543 totalIpc = sum(committedInsts) / numCycles;
544
545 this->fetch.regStats();
546 this->decode.regStats();
547 this->rename.regStats();
548 this->iew.regStats();
549 this->commit.regStats();
550 this->rob.regStats();
551
552 intRegfileReads
553 .name(name() + ".int_regfile_reads")
554 .desc("number of integer regfile reads")
555 .prereq(intRegfileReads);
556
557 intRegfileWrites
558 .name(name() + ".int_regfile_writes")
559 .desc("number of integer regfile writes")
560 .prereq(intRegfileWrites);
561
562 fpRegfileReads
563 .name(name() + ".fp_regfile_reads")
564 .desc("number of floating regfile reads")
565 .prereq(fpRegfileReads);
566
567 fpRegfileWrites
568 .name(name() + ".fp_regfile_writes")
569 .desc("number of floating regfile writes")
570 .prereq(fpRegfileWrites);
571
572 ccRegfileReads
573 .name(name() + ".cc_regfile_reads")
574 .desc("number of cc regfile reads")
575 .prereq(ccRegfileReads);
576
577 ccRegfileWrites
578 .name(name() + ".cc_regfile_writes")
579 .desc("number of cc regfile writes")
580 .prereq(ccRegfileWrites);
581
582 miscRegfileReads
583 .name(name() + ".misc_regfile_reads")
584 .desc("number of misc regfile reads")
585 .prereq(miscRegfileReads);
586
587 miscRegfileWrites
588 .name(name() + ".misc_regfile_writes")
589 .desc("number of misc regfile writes")
590 .prereq(miscRegfileWrites);
591}
592
593template <class Impl>
594void
595FullO3CPU<Impl>::tick()
596{
597 DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
598 assert(!switchedOut());
599 assert(getDrainState() != Drainable::Drained);
600
601 ++numCycles;
602
603// activity = false;
604
605 //Tick each of the stages
606 fetch.tick();
607
608 decode.tick();
609
610 rename.tick();
611
612 iew.tick();
613
614 commit.tick();
615
616 if (!FullSystem)
617 doContextSwitch();
618
619 // Now advance the time buffers
620 timeBuffer.advance();
621
622 fetchQueue.advance();
623 decodeQueue.advance();
624 renameQueue.advance();
625 iewQueue.advance();
626
627 activityRec.advance();
628
629 if (removeInstsThisCycle) {
630 cleanUpRemovedInsts();
631 }
632
633 if (!tickEvent.scheduled()) {
634 if (_status == SwitchedOut) {
635 DPRINTF(O3CPU, "Switched out!\n");
636 // increment stat
637 lastRunningCycle = curCycle();
638 } else if (!activityRec.active() || _status == Idle) {
639 DPRINTF(O3CPU, "Idle!\n");
640 lastRunningCycle = curCycle();
641 timesIdled++;
642 } else {
643 schedule(tickEvent, clockEdge(Cycles(1)));
644 DPRINTF(O3CPU, "Scheduling next tick!\n");
645 }
646 }
647
648 if (!FullSystem)
649 updateThreadPriority();
650
651 tryDrain();
652}
653
654template <class Impl>
655void
656FullO3CPU<Impl>::init()
657{
658 BaseCPU::init();
659
660 for (ThreadID tid = 0; tid < numThreads; ++tid) {
661 // Set noSquashFromTC so that the CPU doesn't squash when initially
662 // setting up registers.
663 thread[tid]->noSquashFromTC = true;
664 // Initialise the ThreadContext's memory proxies
665 thread[tid]->initMemProxies(thread[tid]->getTC());
666 }
667
668 if (FullSystem && !params()->switched_out) {
669 for (ThreadID tid = 0; tid < numThreads; tid++) {
670 ThreadContext *src_tc = threadContexts[tid];
671 TheISA::initCPU(src_tc, src_tc->contextId());
672 }
673 }
674
675 // Clear noSquashFromTC.
676 for (int tid = 0; tid < numThreads; ++tid)
677 thread[tid]->noSquashFromTC = false;
678
679 commit.setThreads(thread);
680}
681
682template <class Impl>
683void
684FullO3CPU<Impl>::startup()
685{
686 BaseCPU::startup();
687 for (int tid = 0; tid < numThreads; ++tid)
688 isa[tid]->startup(threadContexts[tid]);
689
690 fetch.startupStage();
691 decode.startupStage();
692 iew.startupStage();
693 rename.startupStage();
694 commit.startupStage();
695}
696
697template <class Impl>
698void
699FullO3CPU<Impl>::activateThread(ThreadID tid)
700{
701 list<ThreadID>::iterator isActive =
702 std::find(activeThreads.begin(), activeThreads.end(), tid);
703
704 DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid);
705 assert(!switchedOut());
706
707 if (isActive == activeThreads.end()) {
708 DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n",
709 tid);
710
711 activeThreads.push_back(tid);
712 }
713}
714
715template <class Impl>
716void
717FullO3CPU<Impl>::deactivateThread(ThreadID tid)
718{
719 //Remove From Active List, if Active
720 list<ThreadID>::iterator thread_it =
721 std::find(activeThreads.begin(), activeThreads.end(), tid);
722
723 DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid);
724 assert(!switchedOut());
725
726 if (thread_it != activeThreads.end()) {
727 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
728 tid);
729 activeThreads.erase(thread_it);
730 }
731}
732
733template <class Impl>
734Counter
735FullO3CPU<Impl>::totalInsts() const
736{
737 Counter total(0);
738
739 ThreadID size = thread.size();
740 for (ThreadID i = 0; i < size; i++)
741 total += thread[i]->numInst;
742
743 return total;
744}
745
746template <class Impl>
747Counter
748FullO3CPU<Impl>::totalOps() const
749{
750 Counter total(0);
751
752 ThreadID size = thread.size();
753 for (ThreadID i = 0; i < size; i++)
754 total += thread[i]->numOp;
755
756 return total;
757}
758
759template <class Impl>
760void
761FullO3CPU<Impl>::activateContext(ThreadID tid, Cycles delay)
762{
763 assert(!switchedOut());
764
765 // Needs to set each stage to running as well.
766 if (delay){
767 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate "
768 "on cycle %d\n", tid, clockEdge(delay));
769 scheduleActivateThreadEvent(tid, delay);
770 } else {
771 activateThread(tid);
772 }
773
774 // We don't want to wake the CPU if it is drained. In that case,
775 // we just want to flag the thread as active and schedule the tick
776 // event from drainResume() instead.
777 if (getDrainState() == Drainable::Drained)
778 return;
779
780 // If we are time 0 or if the last activation time is in the past,
781 // schedule the next tick and wake up the fetch unit
782 if (lastActivatedCycle == 0 || lastActivatedCycle < curTick()) {
783 scheduleTickEvent(delay);
784
785 // Be sure to signal that there's some activity so the CPU doesn't
786 // deschedule itself.
787 activityRec.activity();
788 fetch.wakeFromQuiesce();
789
790 Cycles cycles(curCycle() - lastRunningCycle);
791 // @todo: This is an oddity that is only here to match the stats
792 if (cycles != 0)
793 --cycles;
794 quiesceCycles += cycles;
795
796 lastActivatedCycle = curTick();
797
798 _status = Running;
799 }
800}
801
802template <class Impl>
803bool
804FullO3CPU<Impl>::scheduleDeallocateContext(ThreadID tid, bool remove,
805 Cycles delay)
806{
807 // Schedule removal of thread data from CPU
808 if (delay){
809 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate "
810 "on tick %d\n", tid, clockEdge(delay));
811 scheduleDeallocateContextEvent(tid, remove, delay);
812 return false;
813 } else {
814 deactivateThread(tid);
815 if (remove)
816 removeThread(tid);
817 return true;
818 }
819}
820
821template <class Impl>
822void
823FullO3CPU<Impl>::suspendContext(ThreadID tid)
824{
825 DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
826 assert(!switchedOut());
827 bool deallocated = scheduleDeallocateContext(tid, false, Cycles(1));
828 // If this was the last thread then unschedule the tick event.
829 if ((activeThreads.size() == 1 && !deallocated) ||
830 activeThreads.size() == 0)
831 unscheduleTickEvent();
832
833 DPRINTF(Quiesce, "Suspending Context\n");
834 lastRunningCycle = curCycle();
835 _status = Idle;
836}
837
838template <class Impl>
839void
840FullO3CPU<Impl>::haltContext(ThreadID tid)
841{
842 //For now, this is the same as deallocate
843 DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
844 assert(!switchedOut());
845 scheduleDeallocateContext(tid, true, Cycles(1));
846}
847
848template <class Impl>
849void
850FullO3CPU<Impl>::insertThread(ThreadID tid)
851{
852 DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU");
853 // Will change now that the PC and thread state is internal to the CPU
854 // and not in the ThreadContext.
855 ThreadContext *src_tc;
856 if (FullSystem)
857 src_tc = system->threadContexts[tid];
858 else
859 src_tc = tcBase(tid);
860
861 //Bind Int Regs to Rename Map
862 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
863 PhysRegIndex phys_reg = freeList.getIntReg();
864
865 renameMap[tid].setEntry(ireg,phys_reg);
866 scoreboard.setReg(phys_reg);
867 }
868
869 //Bind Float Regs to Rename Map
870 int max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs;
871 for (int freg = TheISA::NumIntRegs; freg < max_reg; freg++) {
872 PhysRegIndex phys_reg = freeList.getFloatReg();
873
874 renameMap[tid].setEntry(freg,phys_reg);
875 scoreboard.setReg(phys_reg);
876 }
877
878 //Bind condition-code Regs to Rename Map
879 max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs + TheISA::NumCCRegs;
880 for (int creg = TheISA::NumIntRegs + TheISA::NumFloatRegs;
881 creg < max_reg; creg++) {
882 PhysRegIndex phys_reg = freeList.getCCReg();
883
884 renameMap[tid].setEntry(creg,phys_reg);
885 scoreboard.setReg(phys_reg);
886 }
887
888 //Copy Thread Data Into RegFile
889 //this->copyFromTC(tid);
890
891 //Set PC/NPC/NNPC
892 pcState(src_tc->pcState(), tid);
893
894 src_tc->setStatus(ThreadContext::Active);
895
896 activateContext(tid, Cycles(1));
897
898 //Reset ROB/IQ/LSQ Entries
899 commit.rob->resetEntries();
900 iew.resetEntries();
901}
902
903template <class Impl>
904void
905FullO3CPU<Impl>::removeThread(ThreadID tid)
906{
907 DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid);
908
909 // Copy Thread Data From RegFile
910 // If thread is suspended, it might be re-allocated
911 // this->copyToTC(tid);
912
913
914 // @todo: 2-27-2008: Fix how we free up rename mappings
915 // here to alleviate the case for double-freeing registers
916 // in SMT workloads.
917
918 // Unbind Int Regs from Rename Map
919 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
920 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
921
922 scoreboard.unsetReg(phys_reg);
923 freeList.addReg(phys_reg);
924 }
925
926 // Unbind Float Regs from Rename Map
927 int max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs;
928 for (int freg = TheISA::NumIntRegs; freg < max_reg; freg++) {
929 PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
930
931 scoreboard.unsetReg(phys_reg);
932 freeList.addReg(phys_reg);
933 }
934
935 // Unbind condition-code Regs from Rename Map
936 max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs + TheISA::NumCCRegs;
937 for (int creg = TheISA::NumIntRegs + TheISA::NumFloatRegs;
938 creg < max_reg; creg++) {
939 PhysRegIndex phys_reg = renameMap[tid].lookup(creg);
940
941 scoreboard.unsetReg(phys_reg);
942 freeList.addReg(phys_reg);
943 }
944
945 // Squash Throughout Pipeline
946 DynInstPtr inst = commit.rob->readHeadInst(tid);
947 InstSeqNum squash_seq_num = inst->seqNum;
948 fetch.squash(0, squash_seq_num, inst, tid);
949 decode.squash(tid);
950 rename.squash(squash_seq_num, tid);
951 iew.squash(tid);
952 iew.ldstQueue.squash(squash_seq_num, tid);
953 commit.rob->squash(squash_seq_num, tid);
954
955
956 assert(iew.instQueue.getCount(tid) == 0);
957 assert(iew.ldstQueue.getCount(tid) == 0);
958
959 // Reset ROB/IQ/LSQ Entries
960
961 // Commented out for now. This should be possible to do by
962 // telling all the pipeline stages to drain first, and then
963 // checking until the drain completes. Once the pipeline is
964 // drained, call resetEntries(). - 10-09-06 ktlim
965/*
966 if (activeThreads.size() >= 1) {
967 commit.rob->resetEntries();
968 iew.resetEntries();
969 }
970*/
971}
972
973
974template <class Impl>
975void
976FullO3CPU<Impl>::activateWhenReady(ThreadID tid)
977{
978 DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming"
979 "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
980 tid);
981
982 bool ready = true;
983
984 // Should these all be '<' not '>='? This seems backwards...
985 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
986 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
987 "Phys. Int. Regs.\n",
988 tid);
989 ready = false;
990 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
991 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
992 "Phys. Float. Regs.\n",
993 tid);
994 ready = false;
995 } else if (freeList.numFreeCCRegs() >= TheISA::NumCCRegs) {
996 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
997 "Phys. CC. Regs.\n",
998 tid);
999 ready = false;
1000 } else if (commit.rob->numFreeEntries() >=
1001 commit.rob->entryAmount(activeThreads.size() + 1)) {
1002 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
1003 "ROB entries.\n",
1004 tid);
1005 ready = false;
1006 } else if (iew.instQueue.numFreeEntries() >=
1007 iew.instQueue.entryAmount(activeThreads.size() + 1)) {
1008 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
1009 "IQ entries.\n",
1010 tid);
1011 ready = false;
1/*
2 * Copyright (c) 2011-2012 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
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.
14 *
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.
18 *
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.
29 *
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.
41 *
42 * Authors: Kevin Lim
43 * Korey Sewell
44 * Rick Strong
45 */
46
47#include "arch/kernel_stats.hh"
48#include "config/the_isa.hh"
49#include "cpu/checker/cpu.hh"
50#include "cpu/checker/thread_context.hh"
51#include "cpu/o3/cpu.hh"
52#include "cpu/o3/isa_specific.hh"
53#include "cpu/o3/thread_context.hh"
54#include "cpu/activity.hh"
55#include "cpu/quiesce_event.hh"
56#include "cpu/simple_thread.hh"
57#include "cpu/thread_context.hh"
58#include "debug/Activity.hh"
59#include "debug/Drain.hh"
60#include "debug/O3CPU.hh"
61#include "debug/Quiesce.hh"
62#include "enums/MemoryMode.hh"
63#include "sim/core.hh"
64#include "sim/full_system.hh"
65#include "sim/process.hh"
66#include "sim/stat_control.hh"
67#include "sim/system.hh"
68
69#if THE_ISA == ALPHA_ISA
70#include "arch/alpha/osfpal.hh"
71#include "debug/Activity.hh"
72#endif
73
74struct BaseCPUParams;
75
76using namespace TheISA;
77using namespace std;
78
79BaseO3CPU::BaseO3CPU(BaseCPUParams *params)
80 : BaseCPU(params)
81{
82}
83
84void
85BaseO3CPU::regStats()
86{
87 BaseCPU::regStats();
88}
89
90template<class Impl>
91bool
92FullO3CPU<Impl>::IcachePort::recvTimingResp(PacketPtr pkt)
93{
94 DPRINTF(O3CPU, "Fetch unit received timing\n");
95 // We shouldn't ever get a block in ownership state
96 assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted()));
97 fetch->processCacheCompletion(pkt);
98
99 return true;
100}
101
102template<class Impl>
103void
104FullO3CPU<Impl>::IcachePort::recvRetry()
105{
106 fetch->recvRetry();
107}
108
109template <class Impl>
110bool
111FullO3CPU<Impl>::DcachePort::recvTimingResp(PacketPtr pkt)
112{
113 return lsq->recvTimingResp(pkt);
114}
115
116template <class Impl>
117void
118FullO3CPU<Impl>::DcachePort::recvTimingSnoopReq(PacketPtr pkt)
119{
120 lsq->recvTimingSnoopReq(pkt);
121}
122
123template <class Impl>
124void
125FullO3CPU<Impl>::DcachePort::recvRetry()
126{
127 lsq->recvRetry();
128}
129
130template <class Impl>
131FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
132 : Event(CPU_Tick_Pri), cpu(c)
133{
134}
135
136template <class Impl>
137void
138FullO3CPU<Impl>::TickEvent::process()
139{
140 cpu->tick();
141}
142
143template <class Impl>
144const char *
145FullO3CPU<Impl>::TickEvent::description() const
146{
147 return "FullO3CPU tick";
148}
149
150template <class Impl>
151FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent()
152 : Event(CPU_Switch_Pri)
153{
154}
155
156template <class Impl>
157void
158FullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num,
159 FullO3CPU<Impl> *thread_cpu)
160{
161 tid = thread_num;
162 cpu = thread_cpu;
163}
164
165template <class Impl>
166void
167FullO3CPU<Impl>::ActivateThreadEvent::process()
168{
169 cpu->activateThread(tid);
170}
171
172template <class Impl>
173const char *
174FullO3CPU<Impl>::ActivateThreadEvent::description() const
175{
176 return "FullO3CPU \"Activate Thread\"";
177}
178
179template <class Impl>
180FullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent()
181 : Event(CPU_Tick_Pri), tid(0), remove(false), cpu(NULL)
182{
183}
184
185template <class Impl>
186void
187FullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num,
188 FullO3CPU<Impl> *thread_cpu)
189{
190 tid = thread_num;
191 cpu = thread_cpu;
192 remove = false;
193}
194
195template <class Impl>
196void
197FullO3CPU<Impl>::DeallocateContextEvent::process()
198{
199 cpu->deactivateThread(tid);
200 if (remove)
201 cpu->removeThread(tid);
202}
203
204template <class Impl>
205const char *
206FullO3CPU<Impl>::DeallocateContextEvent::description() const
207{
208 return "FullO3CPU \"Deallocate Context\"";
209}
210
211template <class Impl>
212FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
213 : BaseO3CPU(params),
214 itb(params->itb),
215 dtb(params->dtb),
216 tickEvent(this),
217#ifndef NDEBUG
218 instcount(0),
219#endif
220 removeInstsThisCycle(false),
221 fetch(this, params),
222 decode(this, params),
223 rename(this, params),
224 iew(this, params),
225 commit(this, params),
226
227 regFile(params->numPhysIntRegs,
228 params->numPhysFloatRegs,
229 params->numPhysCCRegs),
230
231 freeList(name() + ".freelist", &regFile),
232
233 rob(this, params),
234
235 scoreboard(name() + ".scoreboard",
236 regFile.totalNumPhysRegs(), TheISA::NumMiscRegs,
237 TheISA::ZeroReg, TheISA::ZeroReg),
238
239 isa(numThreads, NULL),
240
241 icachePort(&fetch, this),
242 dcachePort(&iew.ldstQueue, this),
243
244 timeBuffer(params->backComSize, params->forwardComSize),
245 fetchQueue(params->backComSize, params->forwardComSize),
246 decodeQueue(params->backComSize, params->forwardComSize),
247 renameQueue(params->backComSize, params->forwardComSize),
248 iewQueue(params->backComSize, params->forwardComSize),
249 activityRec(name(), NumStages,
250 params->backComSize + params->forwardComSize,
251 params->activity),
252
253 globalSeqNum(1),
254 system(params->system),
255 drainManager(NULL),
256 lastRunningCycle(curCycle())
257{
258 if (!params->switched_out) {
259 _status = Running;
260 } else {
261 _status = SwitchedOut;
262 }
263
264 if (params->checker) {
265 BaseCPU *temp_checker = params->checker;
266 checker = dynamic_cast<Checker<Impl> *>(temp_checker);
267 checker->setIcachePort(&icachePort);
268 checker->setSystem(params->system);
269 } else {
270 checker = NULL;
271 }
272
273 if (!FullSystem) {
274 thread.resize(numThreads);
275 tids.resize(numThreads);
276 }
277
278 // The stages also need their CPU pointer setup. However this
279 // must be done at the upper level CPU because they have pointers
280 // to the upper level CPU, and not this FullO3CPU.
281
282 // Set up Pointers to the activeThreads list for each stage
283 fetch.setActiveThreads(&activeThreads);
284 decode.setActiveThreads(&activeThreads);
285 rename.setActiveThreads(&activeThreads);
286 iew.setActiveThreads(&activeThreads);
287 commit.setActiveThreads(&activeThreads);
288
289 // Give each of the stages the time buffer they will use.
290 fetch.setTimeBuffer(&timeBuffer);
291 decode.setTimeBuffer(&timeBuffer);
292 rename.setTimeBuffer(&timeBuffer);
293 iew.setTimeBuffer(&timeBuffer);
294 commit.setTimeBuffer(&timeBuffer);
295
296 // Also setup each of the stages' queues.
297 fetch.setFetchQueue(&fetchQueue);
298 decode.setFetchQueue(&fetchQueue);
299 commit.setFetchQueue(&fetchQueue);
300 decode.setDecodeQueue(&decodeQueue);
301 rename.setDecodeQueue(&decodeQueue);
302 rename.setRenameQueue(&renameQueue);
303 iew.setRenameQueue(&renameQueue);
304 iew.setIEWQueue(&iewQueue);
305 commit.setIEWQueue(&iewQueue);
306 commit.setRenameQueue(&renameQueue);
307
308 commit.setIEWStage(&iew);
309 rename.setIEWStage(&iew);
310 rename.setCommitStage(&commit);
311
312 ThreadID active_threads;
313 if (FullSystem) {
314 active_threads = 1;
315 } else {
316 active_threads = params->workload.size();
317
318 if (active_threads > Impl::MaxThreads) {
319 panic("Workload Size too large. Increase the 'MaxThreads' "
320 "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) "
321 "or edit your workload size.");
322 }
323 }
324
325 //Make Sure That this a Valid Architeture
326 assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs);
327 assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
328 assert(params->numPhysCCRegs >= numThreads * TheISA::NumCCRegs);
329
330 rename.setScoreboard(&scoreboard);
331 iew.setScoreboard(&scoreboard);
332
333 // Setup the rename map for whichever stages need it.
334 for (ThreadID tid = 0; tid < numThreads; tid++) {
335 isa[tid] = params->isa[tid];
336
337 // Only Alpha has an FP zero register, so for other ISAs we
338 // use an invalid FP register index to avoid special treatment
339 // of any valid FP reg.
340 RegIndex invalidFPReg = TheISA::NumFloatRegs + 1;
341 RegIndex fpZeroReg =
342 (THE_ISA == ALPHA_ISA) ? TheISA::ZeroReg : invalidFPReg;
343
344 commitRenameMap[tid].init(&regFile, TheISA::ZeroReg, fpZeroReg,
345 &freeList);
346
347 renameMap[tid].init(&regFile, TheISA::ZeroReg, fpZeroReg,
348 &freeList);
349
350 activateThreadEvent[tid].init(tid, this);
351 deallocateContextEvent[tid].init(tid, this);
352 }
353
354 // Initialize rename map to assign physical registers to the
355 // architectural registers for active threads only.
356 for (ThreadID tid = 0; tid < active_threads; tid++) {
357 for (RegIndex ridx = 0; ridx < TheISA::NumIntRegs; ++ridx) {
358 // Note that we can't use the rename() method because we don't
359 // want special treatment for the zero register at this point
360 PhysRegIndex phys_reg = freeList.getIntReg();
361 renameMap[tid].setIntEntry(ridx, phys_reg);
362 commitRenameMap[tid].setIntEntry(ridx, phys_reg);
363 }
364
365 for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) {
366 PhysRegIndex phys_reg = freeList.getFloatReg();
367 renameMap[tid].setFloatEntry(ridx, phys_reg);
368 commitRenameMap[tid].setFloatEntry(ridx, phys_reg);
369 }
370
371 for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) {
372 PhysRegIndex phys_reg = freeList.getCCReg();
373 renameMap[tid].setCCEntry(ridx, phys_reg);
374 commitRenameMap[tid].setCCEntry(ridx, phys_reg);
375 }
376 }
377
378 rename.setRenameMap(renameMap);
379 commit.setRenameMap(commitRenameMap);
380 rename.setFreeList(&freeList);
381
382 // Setup the ROB for whichever stages need it.
383 commit.setROB(&rob);
384
385 lastActivatedCycle = 0;
386#if 0
387 // Give renameMap & rename stage access to the freeList;
388 for (ThreadID tid = 0; tid < numThreads; tid++)
389 globalSeqNum[tid] = 1;
390#endif
391
392 contextSwitch = false;
393 DPRINTF(O3CPU, "Creating O3CPU object.\n");
394
395 // Setup any thread state.
396 this->thread.resize(this->numThreads);
397
398 for (ThreadID tid = 0; tid < this->numThreads; ++tid) {
399 if (FullSystem) {
400 // SMT is not supported in FS mode yet.
401 assert(this->numThreads == 1);
402 this->thread[tid] = new Thread(this, 0, NULL);
403 } else {
404 if (tid < params->workload.size()) {
405 DPRINTF(O3CPU, "Workload[%i] process is %#x",
406 tid, this->thread[tid]);
407 this->thread[tid] = new typename FullO3CPU<Impl>::Thread(
408 (typename Impl::O3CPU *)(this),
409 tid, params->workload[tid]);
410
411 //usedTids[tid] = true;
412 //threadMap[tid] = tid;
413 } else {
414 //Allocate Empty thread so M5 can use later
415 //when scheduling threads to CPU
416 Process* dummy_proc = NULL;
417
418 this->thread[tid] = new typename FullO3CPU<Impl>::Thread(
419 (typename Impl::O3CPU *)(this),
420 tid, dummy_proc);
421 //usedTids[tid] = false;
422 }
423 }
424
425 ThreadContext *tc;
426
427 // Setup the TC that will serve as the interface to the threads/CPU.
428 O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>;
429
430 tc = o3_tc;
431
432 // If we're using a checker, then the TC should be the
433 // CheckerThreadContext.
434 if (params->checker) {
435 tc = new CheckerThreadContext<O3ThreadContext<Impl> >(
436 o3_tc, this->checker);
437 }
438
439 o3_tc->cpu = (typename Impl::O3CPU *)(this);
440 assert(o3_tc->cpu);
441 o3_tc->thread = this->thread[tid];
442
443 if (FullSystem) {
444 // Setup quiesce event.
445 this->thread[tid]->quiesceEvent = new EndQuiesceEvent(tc);
446 }
447 // Give the thread the TC.
448 this->thread[tid]->tc = tc;
449
450 // Add the TC to the CPU's list of TC's.
451 this->threadContexts.push_back(tc);
452 }
453
454 // FullO3CPU always requires an interrupt controller.
455 if (!params->switched_out && !interrupts) {
456 fatal("FullO3CPU %s has no interrupt controller.\n"
457 "Ensure createInterruptController() is called.\n", name());
458 }
459
460 for (ThreadID tid = 0; tid < this->numThreads; tid++)
461 this->thread[tid]->setFuncExeInst(0);
462}
463
464template <class Impl>
465FullO3CPU<Impl>::~FullO3CPU()
466{
467}
468
469template <class Impl>
470void
471FullO3CPU<Impl>::regProbePoints()
472{
473 ppInstAccessComplete = new ProbePointArg<PacketPtr>(getProbeManager(), "InstAccessComplete");
474 ppDataAccessComplete = new ProbePointArg<std::pair<DynInstPtr, PacketPtr> >(getProbeManager(), "DataAccessComplete");
475 fetch.regProbePoints();
476 iew.regProbePoints();
477 commit.regProbePoints();
478}
479
480template <class Impl>
481void
482FullO3CPU<Impl>::regStats()
483{
484 BaseO3CPU::regStats();
485
486 // Register any of the O3CPU's stats here.
487 timesIdled
488 .name(name() + ".timesIdled")
489 .desc("Number of times that the entire CPU went into an idle state and"
490 " unscheduled itself")
491 .prereq(timesIdled);
492
493 idleCycles
494 .name(name() + ".idleCycles")
495 .desc("Total number of cycles that the CPU has spent unscheduled due "
496 "to idling")
497 .prereq(idleCycles);
498
499 quiesceCycles
500 .name(name() + ".quiesceCycles")
501 .desc("Total number of cycles that CPU has spent quiesced or waiting "
502 "for an interrupt")
503 .prereq(quiesceCycles);
504
505 // Number of Instructions simulated
506 // --------------------------------
507 // Should probably be in Base CPU but need templated
508 // MaxThreads so put in here instead
509 committedInsts
510 .init(numThreads)
511 .name(name() + ".committedInsts")
512 .desc("Number of Instructions Simulated")
513 .flags(Stats::total);
514
515 committedOps
516 .init(numThreads)
517 .name(name() + ".committedOps")
518 .desc("Number of Ops (including micro ops) Simulated")
519 .flags(Stats::total);
520
521 cpi
522 .name(name() + ".cpi")
523 .desc("CPI: Cycles Per Instruction")
524 .precision(6);
525 cpi = numCycles / committedInsts;
526
527 totalCpi
528 .name(name() + ".cpi_total")
529 .desc("CPI: Total CPI of All Threads")
530 .precision(6);
531 totalCpi = numCycles / sum(committedInsts);
532
533 ipc
534 .name(name() + ".ipc")
535 .desc("IPC: Instructions Per Cycle")
536 .precision(6);
537 ipc = committedInsts / numCycles;
538
539 totalIpc
540 .name(name() + ".ipc_total")
541 .desc("IPC: Total IPC of All Threads")
542 .precision(6);
543 totalIpc = sum(committedInsts) / numCycles;
544
545 this->fetch.regStats();
546 this->decode.regStats();
547 this->rename.regStats();
548 this->iew.regStats();
549 this->commit.regStats();
550 this->rob.regStats();
551
552 intRegfileReads
553 .name(name() + ".int_regfile_reads")
554 .desc("number of integer regfile reads")
555 .prereq(intRegfileReads);
556
557 intRegfileWrites
558 .name(name() + ".int_regfile_writes")
559 .desc("number of integer regfile writes")
560 .prereq(intRegfileWrites);
561
562 fpRegfileReads
563 .name(name() + ".fp_regfile_reads")
564 .desc("number of floating regfile reads")
565 .prereq(fpRegfileReads);
566
567 fpRegfileWrites
568 .name(name() + ".fp_regfile_writes")
569 .desc("number of floating regfile writes")
570 .prereq(fpRegfileWrites);
571
572 ccRegfileReads
573 .name(name() + ".cc_regfile_reads")
574 .desc("number of cc regfile reads")
575 .prereq(ccRegfileReads);
576
577 ccRegfileWrites
578 .name(name() + ".cc_regfile_writes")
579 .desc("number of cc regfile writes")
580 .prereq(ccRegfileWrites);
581
582 miscRegfileReads
583 .name(name() + ".misc_regfile_reads")
584 .desc("number of misc regfile reads")
585 .prereq(miscRegfileReads);
586
587 miscRegfileWrites
588 .name(name() + ".misc_regfile_writes")
589 .desc("number of misc regfile writes")
590 .prereq(miscRegfileWrites);
591}
592
593template <class Impl>
594void
595FullO3CPU<Impl>::tick()
596{
597 DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
598 assert(!switchedOut());
599 assert(getDrainState() != Drainable::Drained);
600
601 ++numCycles;
602
603// activity = false;
604
605 //Tick each of the stages
606 fetch.tick();
607
608 decode.tick();
609
610 rename.tick();
611
612 iew.tick();
613
614 commit.tick();
615
616 if (!FullSystem)
617 doContextSwitch();
618
619 // Now advance the time buffers
620 timeBuffer.advance();
621
622 fetchQueue.advance();
623 decodeQueue.advance();
624 renameQueue.advance();
625 iewQueue.advance();
626
627 activityRec.advance();
628
629 if (removeInstsThisCycle) {
630 cleanUpRemovedInsts();
631 }
632
633 if (!tickEvent.scheduled()) {
634 if (_status == SwitchedOut) {
635 DPRINTF(O3CPU, "Switched out!\n");
636 // increment stat
637 lastRunningCycle = curCycle();
638 } else if (!activityRec.active() || _status == Idle) {
639 DPRINTF(O3CPU, "Idle!\n");
640 lastRunningCycle = curCycle();
641 timesIdled++;
642 } else {
643 schedule(tickEvent, clockEdge(Cycles(1)));
644 DPRINTF(O3CPU, "Scheduling next tick!\n");
645 }
646 }
647
648 if (!FullSystem)
649 updateThreadPriority();
650
651 tryDrain();
652}
653
654template <class Impl>
655void
656FullO3CPU<Impl>::init()
657{
658 BaseCPU::init();
659
660 for (ThreadID tid = 0; tid < numThreads; ++tid) {
661 // Set noSquashFromTC so that the CPU doesn't squash when initially
662 // setting up registers.
663 thread[tid]->noSquashFromTC = true;
664 // Initialise the ThreadContext's memory proxies
665 thread[tid]->initMemProxies(thread[tid]->getTC());
666 }
667
668 if (FullSystem && !params()->switched_out) {
669 for (ThreadID tid = 0; tid < numThreads; tid++) {
670 ThreadContext *src_tc = threadContexts[tid];
671 TheISA::initCPU(src_tc, src_tc->contextId());
672 }
673 }
674
675 // Clear noSquashFromTC.
676 for (int tid = 0; tid < numThreads; ++tid)
677 thread[tid]->noSquashFromTC = false;
678
679 commit.setThreads(thread);
680}
681
682template <class Impl>
683void
684FullO3CPU<Impl>::startup()
685{
686 BaseCPU::startup();
687 for (int tid = 0; tid < numThreads; ++tid)
688 isa[tid]->startup(threadContexts[tid]);
689
690 fetch.startupStage();
691 decode.startupStage();
692 iew.startupStage();
693 rename.startupStage();
694 commit.startupStage();
695}
696
697template <class Impl>
698void
699FullO3CPU<Impl>::activateThread(ThreadID tid)
700{
701 list<ThreadID>::iterator isActive =
702 std::find(activeThreads.begin(), activeThreads.end(), tid);
703
704 DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid);
705 assert(!switchedOut());
706
707 if (isActive == activeThreads.end()) {
708 DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n",
709 tid);
710
711 activeThreads.push_back(tid);
712 }
713}
714
715template <class Impl>
716void
717FullO3CPU<Impl>::deactivateThread(ThreadID tid)
718{
719 //Remove From Active List, if Active
720 list<ThreadID>::iterator thread_it =
721 std::find(activeThreads.begin(), activeThreads.end(), tid);
722
723 DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid);
724 assert(!switchedOut());
725
726 if (thread_it != activeThreads.end()) {
727 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
728 tid);
729 activeThreads.erase(thread_it);
730 }
731}
732
733template <class Impl>
734Counter
735FullO3CPU<Impl>::totalInsts() const
736{
737 Counter total(0);
738
739 ThreadID size = thread.size();
740 for (ThreadID i = 0; i < size; i++)
741 total += thread[i]->numInst;
742
743 return total;
744}
745
746template <class Impl>
747Counter
748FullO3CPU<Impl>::totalOps() const
749{
750 Counter total(0);
751
752 ThreadID size = thread.size();
753 for (ThreadID i = 0; i < size; i++)
754 total += thread[i]->numOp;
755
756 return total;
757}
758
759template <class Impl>
760void
761FullO3CPU<Impl>::activateContext(ThreadID tid, Cycles delay)
762{
763 assert(!switchedOut());
764
765 // Needs to set each stage to running as well.
766 if (delay){
767 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate "
768 "on cycle %d\n", tid, clockEdge(delay));
769 scheduleActivateThreadEvent(tid, delay);
770 } else {
771 activateThread(tid);
772 }
773
774 // We don't want to wake the CPU if it is drained. In that case,
775 // we just want to flag the thread as active and schedule the tick
776 // event from drainResume() instead.
777 if (getDrainState() == Drainable::Drained)
778 return;
779
780 // If we are time 0 or if the last activation time is in the past,
781 // schedule the next tick and wake up the fetch unit
782 if (lastActivatedCycle == 0 || lastActivatedCycle < curTick()) {
783 scheduleTickEvent(delay);
784
785 // Be sure to signal that there's some activity so the CPU doesn't
786 // deschedule itself.
787 activityRec.activity();
788 fetch.wakeFromQuiesce();
789
790 Cycles cycles(curCycle() - lastRunningCycle);
791 // @todo: This is an oddity that is only here to match the stats
792 if (cycles != 0)
793 --cycles;
794 quiesceCycles += cycles;
795
796 lastActivatedCycle = curTick();
797
798 _status = Running;
799 }
800}
801
802template <class Impl>
803bool
804FullO3CPU<Impl>::scheduleDeallocateContext(ThreadID tid, bool remove,
805 Cycles delay)
806{
807 // Schedule removal of thread data from CPU
808 if (delay){
809 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate "
810 "on tick %d\n", tid, clockEdge(delay));
811 scheduleDeallocateContextEvent(tid, remove, delay);
812 return false;
813 } else {
814 deactivateThread(tid);
815 if (remove)
816 removeThread(tid);
817 return true;
818 }
819}
820
821template <class Impl>
822void
823FullO3CPU<Impl>::suspendContext(ThreadID tid)
824{
825 DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
826 assert(!switchedOut());
827 bool deallocated = scheduleDeallocateContext(tid, false, Cycles(1));
828 // If this was the last thread then unschedule the tick event.
829 if ((activeThreads.size() == 1 && !deallocated) ||
830 activeThreads.size() == 0)
831 unscheduleTickEvent();
832
833 DPRINTF(Quiesce, "Suspending Context\n");
834 lastRunningCycle = curCycle();
835 _status = Idle;
836}
837
838template <class Impl>
839void
840FullO3CPU<Impl>::haltContext(ThreadID tid)
841{
842 //For now, this is the same as deallocate
843 DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
844 assert(!switchedOut());
845 scheduleDeallocateContext(tid, true, Cycles(1));
846}
847
848template <class Impl>
849void
850FullO3CPU<Impl>::insertThread(ThreadID tid)
851{
852 DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU");
853 // Will change now that the PC and thread state is internal to the CPU
854 // and not in the ThreadContext.
855 ThreadContext *src_tc;
856 if (FullSystem)
857 src_tc = system->threadContexts[tid];
858 else
859 src_tc = tcBase(tid);
860
861 //Bind Int Regs to Rename Map
862 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
863 PhysRegIndex phys_reg = freeList.getIntReg();
864
865 renameMap[tid].setEntry(ireg,phys_reg);
866 scoreboard.setReg(phys_reg);
867 }
868
869 //Bind Float Regs to Rename Map
870 int max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs;
871 for (int freg = TheISA::NumIntRegs; freg < max_reg; freg++) {
872 PhysRegIndex phys_reg = freeList.getFloatReg();
873
874 renameMap[tid].setEntry(freg,phys_reg);
875 scoreboard.setReg(phys_reg);
876 }
877
878 //Bind condition-code Regs to Rename Map
879 max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs + TheISA::NumCCRegs;
880 for (int creg = TheISA::NumIntRegs + TheISA::NumFloatRegs;
881 creg < max_reg; creg++) {
882 PhysRegIndex phys_reg = freeList.getCCReg();
883
884 renameMap[tid].setEntry(creg,phys_reg);
885 scoreboard.setReg(phys_reg);
886 }
887
888 //Copy Thread Data Into RegFile
889 //this->copyFromTC(tid);
890
891 //Set PC/NPC/NNPC
892 pcState(src_tc->pcState(), tid);
893
894 src_tc->setStatus(ThreadContext::Active);
895
896 activateContext(tid, Cycles(1));
897
898 //Reset ROB/IQ/LSQ Entries
899 commit.rob->resetEntries();
900 iew.resetEntries();
901}
902
903template <class Impl>
904void
905FullO3CPU<Impl>::removeThread(ThreadID tid)
906{
907 DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid);
908
909 // Copy Thread Data From RegFile
910 // If thread is suspended, it might be re-allocated
911 // this->copyToTC(tid);
912
913
914 // @todo: 2-27-2008: Fix how we free up rename mappings
915 // here to alleviate the case for double-freeing registers
916 // in SMT workloads.
917
918 // Unbind Int Regs from Rename Map
919 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
920 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
921
922 scoreboard.unsetReg(phys_reg);
923 freeList.addReg(phys_reg);
924 }
925
926 // Unbind Float Regs from Rename Map
927 int max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs;
928 for (int freg = TheISA::NumIntRegs; freg < max_reg; freg++) {
929 PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
930
931 scoreboard.unsetReg(phys_reg);
932 freeList.addReg(phys_reg);
933 }
934
935 // Unbind condition-code Regs from Rename Map
936 max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs + TheISA::NumCCRegs;
937 for (int creg = TheISA::NumIntRegs + TheISA::NumFloatRegs;
938 creg < max_reg; creg++) {
939 PhysRegIndex phys_reg = renameMap[tid].lookup(creg);
940
941 scoreboard.unsetReg(phys_reg);
942 freeList.addReg(phys_reg);
943 }
944
945 // Squash Throughout Pipeline
946 DynInstPtr inst = commit.rob->readHeadInst(tid);
947 InstSeqNum squash_seq_num = inst->seqNum;
948 fetch.squash(0, squash_seq_num, inst, tid);
949 decode.squash(tid);
950 rename.squash(squash_seq_num, tid);
951 iew.squash(tid);
952 iew.ldstQueue.squash(squash_seq_num, tid);
953 commit.rob->squash(squash_seq_num, tid);
954
955
956 assert(iew.instQueue.getCount(tid) == 0);
957 assert(iew.ldstQueue.getCount(tid) == 0);
958
959 // Reset ROB/IQ/LSQ Entries
960
961 // Commented out for now. This should be possible to do by
962 // telling all the pipeline stages to drain first, and then
963 // checking until the drain completes. Once the pipeline is
964 // drained, call resetEntries(). - 10-09-06 ktlim
965/*
966 if (activeThreads.size() >= 1) {
967 commit.rob->resetEntries();
968 iew.resetEntries();
969 }
970*/
971}
972
973
974template <class Impl>
975void
976FullO3CPU<Impl>::activateWhenReady(ThreadID tid)
977{
978 DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming"
979 "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
980 tid);
981
982 bool ready = true;
983
984 // Should these all be '<' not '>='? This seems backwards...
985 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
986 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
987 "Phys. Int. Regs.\n",
988 tid);
989 ready = false;
990 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
991 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
992 "Phys. Float. Regs.\n",
993 tid);
994 ready = false;
995 } else if (freeList.numFreeCCRegs() >= TheISA::NumCCRegs) {
996 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
997 "Phys. CC. Regs.\n",
998 tid);
999 ready = false;
1000 } else if (commit.rob->numFreeEntries() >=
1001 commit.rob->entryAmount(activeThreads.size() + 1)) {
1002 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
1003 "ROB entries.\n",
1004 tid);
1005 ready = false;
1006 } else if (iew.instQueue.numFreeEntries() >=
1007 iew.instQueue.entryAmount(activeThreads.size() + 1)) {
1008 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
1009 "IQ entries.\n",
1010 tid);
1011 ready = false;
1012 } else if (iew.ldstQueue.numFreeEntries() >=
1012 } else if (iew.ldstQueue.numFreeLoadEntries() >=
1013 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
1014 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
1013 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
1014 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
1015 "LSQ entries.\n",
1015 "LQ entries.\n",
1016 tid);
1017 ready = false;
1016 tid);
1017 ready = false;
1018 } else if (iew.ldstQueue.numFreeStoreEntries() >=
1019 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
1020 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
1021 "SQ entries.\n",
1022 tid);
1023 ready = false;
1018 }
1019
1020 if (ready) {
1021 insertThread(tid);
1022
1023 contextSwitch = false;
1024
1025 cpuWaitList.remove(tid);
1026 } else {
1027 suspendContext(tid);
1028
1029 //blocks fetch
1030 contextSwitch = true;
1031
1032 //@todo: dont always add to waitlist
1033 //do waitlist
1034 cpuWaitList.push_back(tid);
1035 }
1036}
1037
1038template <class Impl>
1039Fault
1040FullO3CPU<Impl>::hwrei(ThreadID tid)
1041{
1042#if THE_ISA == ALPHA_ISA
1043 // Need to clear the lock flag upon returning from an interrupt.
1044 this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid);
1045
1046 this->thread[tid]->kernelStats->hwrei();
1047
1048 // FIXME: XXX check for interrupts? XXX
1049#endif
1050 return NoFault;
1051}
1052
1053template <class Impl>
1054bool
1055FullO3CPU<Impl>::simPalCheck(int palFunc, ThreadID tid)
1056{
1057#if THE_ISA == ALPHA_ISA
1058 if (this->thread[tid]->kernelStats)
1059 this->thread[tid]->kernelStats->callpal(palFunc,
1060 this->threadContexts[tid]);
1061
1062 switch (palFunc) {
1063 case PAL::halt:
1064 halt();
1065 if (--System::numSystemsRunning == 0)
1066 exitSimLoop("all cpus halted");
1067 break;
1068
1069 case PAL::bpt:
1070 case PAL::bugchk:
1071 if (this->system->breakpoint())
1072 return false;
1073 break;
1074 }
1075#endif
1076 return true;
1077}
1078
1079template <class Impl>
1080Fault
1081FullO3CPU<Impl>::getInterrupts()
1082{
1083 // Check if there are any outstanding interrupts
1084 return this->interrupts->getInterrupt(this->threadContexts[0]);
1085}
1086
1087template <class Impl>
1088void
1089FullO3CPU<Impl>::processInterrupts(Fault interrupt)
1090{
1091 // Check for interrupts here. For now can copy the code that
1092 // exists within isa_fullsys_traits.hh. Also assume that thread 0
1093 // is the one that handles the interrupts.
1094 // @todo: Possibly consolidate the interrupt checking code.
1095 // @todo: Allow other threads to handle interrupts.
1096
1097 assert(interrupt != NoFault);
1098 this->interrupts->updateIntrInfo(this->threadContexts[0]);
1099
1100 DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name());
1101 this->trap(interrupt, 0, NULL);
1102}
1103
1104template <class Impl>
1105void
1106FullO3CPU<Impl>::trap(Fault fault, ThreadID tid, StaticInstPtr inst)
1107{
1108 // Pass the thread's TC into the invoke method.
1109 fault->invoke(this->threadContexts[tid], inst);
1110}
1111
1112template <class Impl>
1113void
1114FullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid)
1115{
1116 DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
1117
1118 DPRINTF(Activity,"Activity: syscall() called.\n");
1119
1120 // Temporarily increase this by one to account for the syscall
1121 // instruction.
1122 ++(this->thread[tid]->funcExeInst);
1123
1124 // Execute the actual syscall.
1125 this->thread[tid]->syscall(callnum);
1126
1127 // Decrease funcExeInst by one as the normal commit will handle
1128 // incrementing it.
1129 --(this->thread[tid]->funcExeInst);
1130}
1131
1132template <class Impl>
1133void
1134FullO3CPU<Impl>::serializeThread(std::ostream &os, ThreadID tid)
1135{
1136 thread[tid]->serialize(os);
1137}
1138
1139template <class Impl>
1140void
1141FullO3CPU<Impl>::unserializeThread(Checkpoint *cp, const std::string &section,
1142 ThreadID tid)
1143{
1144 thread[tid]->unserialize(cp, section);
1145}
1146
1147template <class Impl>
1148unsigned int
1149FullO3CPU<Impl>::drain(DrainManager *drain_manager)
1150{
1151 // If the CPU isn't doing anything, then return immediately.
1152 if (switchedOut()) {
1153 setDrainState(Drainable::Drained);
1154 return 0;
1155 }
1156
1157 DPRINTF(Drain, "Draining...\n");
1158 setDrainState(Drainable::Draining);
1159
1160 // We only need to signal a drain to the commit stage as this
1161 // initiates squashing controls the draining. Once the commit
1162 // stage commits an instruction where it is safe to stop, it'll
1163 // squash the rest of the instructions in the pipeline and force
1164 // the fetch stage to stall. The pipeline will be drained once all
1165 // in-flight instructions have retired.
1166 commit.drain();
1167
1168 // Wake the CPU and record activity so everything can drain out if
1169 // the CPU was not able to immediately drain.
1170 if (!isDrained()) {
1171 drainManager = drain_manager;
1172
1173 wakeCPU();
1174 activityRec.activity();
1175
1176 DPRINTF(Drain, "CPU not drained\n");
1177
1178 return 1;
1179 } else {
1180 setDrainState(Drainable::Drained);
1181 DPRINTF(Drain, "CPU is already drained\n");
1182 if (tickEvent.scheduled())
1183 deschedule(tickEvent);
1184
1185 // Flush out any old data from the time buffers. In
1186 // particular, there might be some data in flight from the
1187 // fetch stage that isn't visible in any of the CPU buffers we
1188 // test in isDrained().
1189 for (int i = 0; i < timeBuffer.getSize(); ++i) {
1190 timeBuffer.advance();
1191 fetchQueue.advance();
1192 decodeQueue.advance();
1193 renameQueue.advance();
1194 iewQueue.advance();
1195 }
1196
1197 drainSanityCheck();
1198 return 0;
1199 }
1200}
1201
1202template <class Impl>
1203bool
1204FullO3CPU<Impl>::tryDrain()
1205{
1206 if (!drainManager || !isDrained())
1207 return false;
1208
1209 if (tickEvent.scheduled())
1210 deschedule(tickEvent);
1211
1212 DPRINTF(Drain, "CPU done draining, processing drain event\n");
1213 drainManager->signalDrainDone();
1214 drainManager = NULL;
1215
1216 return true;
1217}
1218
1219template <class Impl>
1220void
1221FullO3CPU<Impl>::drainSanityCheck() const
1222{
1223 assert(isDrained());
1224 fetch.drainSanityCheck();
1225 decode.drainSanityCheck();
1226 rename.drainSanityCheck();
1227 iew.drainSanityCheck();
1228 commit.drainSanityCheck();
1229}
1230
1231template <class Impl>
1232bool
1233FullO3CPU<Impl>::isDrained() const
1234{
1235 bool drained(true);
1236
1237 for (ThreadID i = 0; i < thread.size(); ++i) {
1238 if (activateThreadEvent[i].scheduled()) {
1239 DPRINTF(Drain, "CPU not drained, tread %i has a "
1240 "pending activate event\n", i);
1241 drained = false;
1242 }
1243 if (deallocateContextEvent[i].scheduled()) {
1244 DPRINTF(Drain, "CPU not drained, tread %i has a "
1245 "pending deallocate context event\n", i);
1246 drained = false;
1247 }
1248 }
1249
1250 if (!instList.empty() || !removeList.empty()) {
1251 DPRINTF(Drain, "Main CPU structures not drained.\n");
1252 drained = false;
1253 }
1254
1255 if (!fetch.isDrained()) {
1256 DPRINTF(Drain, "Fetch not drained.\n");
1257 drained = false;
1258 }
1259
1260 if (!decode.isDrained()) {
1261 DPRINTF(Drain, "Decode not drained.\n");
1262 drained = false;
1263 }
1264
1265 if (!rename.isDrained()) {
1266 DPRINTF(Drain, "Rename not drained.\n");
1267 drained = false;
1268 }
1269
1270 if (!iew.isDrained()) {
1271 DPRINTF(Drain, "IEW not drained.\n");
1272 drained = false;
1273 }
1274
1275 if (!commit.isDrained()) {
1276 DPRINTF(Drain, "Commit not drained.\n");
1277 drained = false;
1278 }
1279
1280 return drained;
1281}
1282
1283template <class Impl>
1284void
1285FullO3CPU<Impl>::commitDrained(ThreadID tid)
1286{
1287 fetch.drainStall(tid);
1288}
1289
1290template <class Impl>
1291void
1292FullO3CPU<Impl>::drainResume()
1293{
1294 setDrainState(Drainable::Running);
1295 if (switchedOut())
1296 return;
1297
1298 DPRINTF(Drain, "Resuming...\n");
1299 verifyMemoryMode();
1300
1301 fetch.drainResume();
1302 commit.drainResume();
1303
1304 _status = Idle;
1305 for (ThreadID i = 0; i < thread.size(); i++) {
1306 if (thread[i]->status() == ThreadContext::Active) {
1307 DPRINTF(Drain, "Activating thread: %i\n", i);
1308 activateThread(i);
1309 _status = Running;
1310 }
1311 }
1312
1313 assert(!tickEvent.scheduled());
1314 if (_status == Running)
1315 schedule(tickEvent, nextCycle());
1316}
1317
1318template <class Impl>
1319void
1320FullO3CPU<Impl>::switchOut()
1321{
1322 DPRINTF(O3CPU, "Switching out\n");
1323 BaseCPU::switchOut();
1324
1325 activityRec.reset();
1326
1327 _status = SwitchedOut;
1328
1329 if (checker)
1330 checker->switchOut();
1331}
1332
1333template <class Impl>
1334void
1335FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
1336{
1337 BaseCPU::takeOverFrom(oldCPU);
1338
1339 fetch.takeOverFrom();
1340 decode.takeOverFrom();
1341 rename.takeOverFrom();
1342 iew.takeOverFrom();
1343 commit.takeOverFrom();
1344
1345 assert(!tickEvent.scheduled());
1346
1347 FullO3CPU<Impl> *oldO3CPU = dynamic_cast<FullO3CPU<Impl>*>(oldCPU);
1348 if (oldO3CPU)
1349 globalSeqNum = oldO3CPU->globalSeqNum;
1350
1351 lastRunningCycle = curCycle();
1352 _status = Idle;
1353}
1354
1355template <class Impl>
1356void
1357FullO3CPU<Impl>::verifyMemoryMode() const
1358{
1359 if (!system->isTimingMode()) {
1360 fatal("The O3 CPU requires the memory system to be in "
1361 "'timing' mode.\n");
1362 }
1363}
1364
1365template <class Impl>
1366TheISA::MiscReg
1367FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid)
1368{
1369 return this->isa[tid]->readMiscRegNoEffect(misc_reg);
1370}
1371
1372template <class Impl>
1373TheISA::MiscReg
1374FullO3CPU<Impl>::readMiscReg(int misc_reg, ThreadID tid)
1375{
1376 miscRegfileReads++;
1377 return this->isa[tid]->readMiscReg(misc_reg, tcBase(tid));
1378}
1379
1380template <class Impl>
1381void
1382FullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg,
1383 const TheISA::MiscReg &val, ThreadID tid)
1384{
1385 this->isa[tid]->setMiscRegNoEffect(misc_reg, val);
1386}
1387
1388template <class Impl>
1389void
1390FullO3CPU<Impl>::setMiscReg(int misc_reg,
1391 const TheISA::MiscReg &val, ThreadID tid)
1392{
1393 miscRegfileWrites++;
1394 this->isa[tid]->setMiscReg(misc_reg, val, tcBase(tid));
1395}
1396
1397template <class Impl>
1398uint64_t
1399FullO3CPU<Impl>::readIntReg(int reg_idx)
1400{
1401 intRegfileReads++;
1402 return regFile.readIntReg(reg_idx);
1403}
1404
1405template <class Impl>
1406FloatReg
1407FullO3CPU<Impl>::readFloatReg(int reg_idx)
1408{
1409 fpRegfileReads++;
1410 return regFile.readFloatReg(reg_idx);
1411}
1412
1413template <class Impl>
1414FloatRegBits
1415FullO3CPU<Impl>::readFloatRegBits(int reg_idx)
1416{
1417 fpRegfileReads++;
1418 return regFile.readFloatRegBits(reg_idx);
1419}
1420
1421template <class Impl>
1422CCReg
1423FullO3CPU<Impl>::readCCReg(int reg_idx)
1424{
1425 ccRegfileReads++;
1426 return regFile.readCCReg(reg_idx);
1427}
1428
1429template <class Impl>
1430void
1431FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
1432{
1433 intRegfileWrites++;
1434 regFile.setIntReg(reg_idx, val);
1435}
1436
1437template <class Impl>
1438void
1439FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val)
1440{
1441 fpRegfileWrites++;
1442 regFile.setFloatReg(reg_idx, val);
1443}
1444
1445template <class Impl>
1446void
1447FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
1448{
1449 fpRegfileWrites++;
1450 regFile.setFloatRegBits(reg_idx, val);
1451}
1452
1453template <class Impl>
1454void
1455FullO3CPU<Impl>::setCCReg(int reg_idx, CCReg val)
1456{
1457 ccRegfileWrites++;
1458 regFile.setCCReg(reg_idx, val);
1459}
1460
1461template <class Impl>
1462uint64_t
1463FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid)
1464{
1465 intRegfileReads++;
1466 PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx);
1467
1468 return regFile.readIntReg(phys_reg);
1469}
1470
1471template <class Impl>
1472float
1473FullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid)
1474{
1475 fpRegfileReads++;
1476 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
1477
1478 return regFile.readFloatReg(phys_reg);
1479}
1480
1481template <class Impl>
1482uint64_t
1483FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid)
1484{
1485 fpRegfileReads++;
1486 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
1487
1488 return regFile.readFloatRegBits(phys_reg);
1489}
1490
1491template <class Impl>
1492CCReg
1493FullO3CPU<Impl>::readArchCCReg(int reg_idx, ThreadID tid)
1494{
1495 ccRegfileReads++;
1496 PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx);
1497
1498 return regFile.readCCReg(phys_reg);
1499}
1500
1501template <class Impl>
1502void
1503FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid)
1504{
1505 intRegfileWrites++;
1506 PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx);
1507
1508 regFile.setIntReg(phys_reg, val);
1509}
1510
1511template <class Impl>
1512void
1513FullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid)
1514{
1515 fpRegfileWrites++;
1516 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
1517
1518 regFile.setFloatReg(phys_reg, val);
1519}
1520
1521template <class Impl>
1522void
1523FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid)
1524{
1525 fpRegfileWrites++;
1526 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
1527
1528 regFile.setFloatRegBits(phys_reg, val);
1529}
1530
1531template <class Impl>
1532void
1533FullO3CPU<Impl>::setArchCCReg(int reg_idx, CCReg val, ThreadID tid)
1534{
1535 ccRegfileWrites++;
1536 PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx);
1537
1538 regFile.setCCReg(phys_reg, val);
1539}
1540
1541template <class Impl>
1542TheISA::PCState
1543FullO3CPU<Impl>::pcState(ThreadID tid)
1544{
1545 return commit.pcState(tid);
1546}
1547
1548template <class Impl>
1549void
1550FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid)
1551{
1552 commit.pcState(val, tid);
1553}
1554
1555template <class Impl>
1556Addr
1557FullO3CPU<Impl>::instAddr(ThreadID tid)
1558{
1559 return commit.instAddr(tid);
1560}
1561
1562template <class Impl>
1563Addr
1564FullO3CPU<Impl>::nextInstAddr(ThreadID tid)
1565{
1566 return commit.nextInstAddr(tid);
1567}
1568
1569template <class Impl>
1570MicroPC
1571FullO3CPU<Impl>::microPC(ThreadID tid)
1572{
1573 return commit.microPC(tid);
1574}
1575
1576template <class Impl>
1577void
1578FullO3CPU<Impl>::squashFromTC(ThreadID tid)
1579{
1580 this->thread[tid]->noSquashFromTC = true;
1581 this->commit.generateTCEvent(tid);
1582}
1583
1584template <class Impl>
1585typename FullO3CPU<Impl>::ListIt
1586FullO3CPU<Impl>::addInst(DynInstPtr &inst)
1587{
1588 instList.push_back(inst);
1589
1590 return --(instList.end());
1591}
1592
1593template <class Impl>
1594void
1595FullO3CPU<Impl>::instDone(ThreadID tid, DynInstPtr &inst)
1596{
1597 // Keep an instruction count.
1598 if (!inst->isMicroop() || inst->isLastMicroop()) {
1599 thread[tid]->numInst++;
1600 thread[tid]->numInsts++;
1601 committedInsts[tid]++;
1602 }
1603 thread[tid]->numOp++;
1604 thread[tid]->numOps++;
1605 committedOps[tid]++;
1606
1607 system->totalNumInsts++;
1608 // Check for instruction-count-based events.
1609 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
1610 system->instEventQueue.serviceEvents(system->totalNumInsts);
1611}
1612
1613template <class Impl>
1614void
1615FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
1616{
1617 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s "
1618 "[sn:%lli]\n",
1619 inst->threadNumber, inst->pcState(), inst->seqNum);
1620
1621 removeInstsThisCycle = true;
1622
1623 // Remove the front instruction.
1624 removeList.push(inst->getInstListIt());
1625}
1626
1627template <class Impl>
1628void
1629FullO3CPU<Impl>::removeInstsNotInROB(ThreadID tid)
1630{
1631 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction"
1632 " list.\n", tid);
1633
1634 ListIt end_it;
1635
1636 bool rob_empty = false;
1637
1638 if (instList.empty()) {
1639 return;
1640 } else if (rob.isEmpty(tid)) {
1641 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n");
1642 end_it = instList.begin();
1643 rob_empty = true;
1644 } else {
1645 end_it = (rob.readTailInst(tid))->getInstListIt();
1646 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n");
1647 }
1648
1649 removeInstsThisCycle = true;
1650
1651 ListIt inst_it = instList.end();
1652
1653 inst_it--;
1654
1655 // Walk through the instruction list, removing any instructions
1656 // that were inserted after the given instruction iterator, end_it.
1657 while (inst_it != end_it) {
1658 assert(!instList.empty());
1659
1660 squashInstIt(inst_it, tid);
1661
1662 inst_it--;
1663 }
1664
1665 // If the ROB was empty, then we actually need to remove the first
1666 // instruction as well.
1667 if (rob_empty) {
1668 squashInstIt(inst_it, tid);
1669 }
1670}
1671
1672template <class Impl>
1673void
1674FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid)
1675{
1676 assert(!instList.empty());
1677
1678 removeInstsThisCycle = true;
1679
1680 ListIt inst_iter = instList.end();
1681
1682 inst_iter--;
1683
1684 DPRINTF(O3CPU, "Deleting instructions from instruction "
1685 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1686 tid, seq_num, (*inst_iter)->seqNum);
1687
1688 while ((*inst_iter)->seqNum > seq_num) {
1689
1690 bool break_loop = (inst_iter == instList.begin());
1691
1692 squashInstIt(inst_iter, tid);
1693
1694 inst_iter--;
1695
1696 if (break_loop)
1697 break;
1698 }
1699}
1700
1701template <class Impl>
1702inline void
1703FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid)
1704{
1705 if ((*instIt)->threadNumber == tid) {
1706 DPRINTF(O3CPU, "Squashing instruction, "
1707 "[tid:%i] [sn:%lli] PC %s\n",
1708 (*instIt)->threadNumber,
1709 (*instIt)->seqNum,
1710 (*instIt)->pcState());
1711
1712 // Mark it as squashed.
1713 (*instIt)->setSquashed();
1714
1715 // @todo: Formulate a consistent method for deleting
1716 // instructions from the instruction list
1717 // Remove the instruction from the list.
1718 removeList.push(instIt);
1719 }
1720}
1721
1722template <class Impl>
1723void
1724FullO3CPU<Impl>::cleanUpRemovedInsts()
1725{
1726 while (!removeList.empty()) {
1727 DPRINTF(O3CPU, "Removing instruction, "
1728 "[tid:%i] [sn:%lli] PC %s\n",
1729 (*removeList.front())->threadNumber,
1730 (*removeList.front())->seqNum,
1731 (*removeList.front())->pcState());
1732
1733 instList.erase(removeList.front());
1734
1735 removeList.pop();
1736 }
1737
1738 removeInstsThisCycle = false;
1739}
1740/*
1741template <class Impl>
1742void
1743FullO3CPU<Impl>::removeAllInsts()
1744{
1745 instList.clear();
1746}
1747*/
1748template <class Impl>
1749void
1750FullO3CPU<Impl>::dumpInsts()
1751{
1752 int num = 0;
1753
1754 ListIt inst_list_it = instList.begin();
1755
1756 cprintf("Dumping Instruction List\n");
1757
1758 while (inst_list_it != instList.end()) {
1759 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1760 "Squashed:%i\n\n",
1761 num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber,
1762 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
1763 (*inst_list_it)->isSquashed());
1764 inst_list_it++;
1765 ++num;
1766 }
1767}
1768/*
1769template <class Impl>
1770void
1771FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
1772{
1773 iew.wakeDependents(inst);
1774}
1775*/
1776template <class Impl>
1777void
1778FullO3CPU<Impl>::wakeCPU()
1779{
1780 if (activityRec.active() || tickEvent.scheduled()) {
1781 DPRINTF(Activity, "CPU already running.\n");
1782 return;
1783 }
1784
1785 DPRINTF(Activity, "Waking up CPU\n");
1786
1787 Cycles cycles(curCycle() - lastRunningCycle);
1788 // @todo: This is an oddity that is only here to match the stats
1789 if (cycles != 0)
1790 --cycles;
1791 idleCycles += cycles;
1792 numCycles += cycles;
1793
1794 schedule(tickEvent, clockEdge());
1795}
1796
1797template <class Impl>
1798void
1799FullO3CPU<Impl>::wakeup()
1800{
1801 if (this->thread[0]->status() != ThreadContext::Suspended)
1802 return;
1803
1804 this->wakeCPU();
1805
1806 DPRINTF(Quiesce, "Suspended Processor woken\n");
1807 this->threadContexts[0]->activate();
1808}
1809
1810template <class Impl>
1811ThreadID
1812FullO3CPU<Impl>::getFreeTid()
1813{
1814 for (ThreadID tid = 0; tid < numThreads; tid++) {
1815 if (!tids[tid]) {
1816 tids[tid] = true;
1817 return tid;
1818 }
1819 }
1820
1821 return InvalidThreadID;
1822}
1823
1824template <class Impl>
1825void
1826FullO3CPU<Impl>::doContextSwitch()
1827{
1828 if (contextSwitch) {
1829
1830 //ADD CODE TO DEACTIVE THREAD HERE (???)
1831
1832 ThreadID size = cpuWaitList.size();
1833 for (ThreadID tid = 0; tid < size; tid++) {
1834 activateWhenReady(tid);
1835 }
1836
1837 if (cpuWaitList.size() == 0)
1838 contextSwitch = true;
1839 }
1840}
1841
1842template <class Impl>
1843void
1844FullO3CPU<Impl>::updateThreadPriority()
1845{
1846 if (activeThreads.size() > 1) {
1847 //DEFAULT TO ROUND ROBIN SCHEME
1848 //e.g. Move highest priority to end of thread list
1849 list<ThreadID>::iterator list_begin = activeThreads.begin();
1850
1851 unsigned high_thread = *list_begin;
1852
1853 activeThreads.erase(list_begin);
1854
1855 activeThreads.push_back(high_thread);
1856 }
1857}
1858
1859// Forward declaration of FullO3CPU.
1860template class FullO3CPU<O3CPUImpl>;
1024 }
1025
1026 if (ready) {
1027 insertThread(tid);
1028
1029 contextSwitch = false;
1030
1031 cpuWaitList.remove(tid);
1032 } else {
1033 suspendContext(tid);
1034
1035 //blocks fetch
1036 contextSwitch = true;
1037
1038 //@todo: dont always add to waitlist
1039 //do waitlist
1040 cpuWaitList.push_back(tid);
1041 }
1042}
1043
1044template <class Impl>
1045Fault
1046FullO3CPU<Impl>::hwrei(ThreadID tid)
1047{
1048#if THE_ISA == ALPHA_ISA
1049 // Need to clear the lock flag upon returning from an interrupt.
1050 this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid);
1051
1052 this->thread[tid]->kernelStats->hwrei();
1053
1054 // FIXME: XXX check for interrupts? XXX
1055#endif
1056 return NoFault;
1057}
1058
1059template <class Impl>
1060bool
1061FullO3CPU<Impl>::simPalCheck(int palFunc, ThreadID tid)
1062{
1063#if THE_ISA == ALPHA_ISA
1064 if (this->thread[tid]->kernelStats)
1065 this->thread[tid]->kernelStats->callpal(palFunc,
1066 this->threadContexts[tid]);
1067
1068 switch (palFunc) {
1069 case PAL::halt:
1070 halt();
1071 if (--System::numSystemsRunning == 0)
1072 exitSimLoop("all cpus halted");
1073 break;
1074
1075 case PAL::bpt:
1076 case PAL::bugchk:
1077 if (this->system->breakpoint())
1078 return false;
1079 break;
1080 }
1081#endif
1082 return true;
1083}
1084
1085template <class Impl>
1086Fault
1087FullO3CPU<Impl>::getInterrupts()
1088{
1089 // Check if there are any outstanding interrupts
1090 return this->interrupts->getInterrupt(this->threadContexts[0]);
1091}
1092
1093template <class Impl>
1094void
1095FullO3CPU<Impl>::processInterrupts(Fault interrupt)
1096{
1097 // Check for interrupts here. For now can copy the code that
1098 // exists within isa_fullsys_traits.hh. Also assume that thread 0
1099 // is the one that handles the interrupts.
1100 // @todo: Possibly consolidate the interrupt checking code.
1101 // @todo: Allow other threads to handle interrupts.
1102
1103 assert(interrupt != NoFault);
1104 this->interrupts->updateIntrInfo(this->threadContexts[0]);
1105
1106 DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name());
1107 this->trap(interrupt, 0, NULL);
1108}
1109
1110template <class Impl>
1111void
1112FullO3CPU<Impl>::trap(Fault fault, ThreadID tid, StaticInstPtr inst)
1113{
1114 // Pass the thread's TC into the invoke method.
1115 fault->invoke(this->threadContexts[tid], inst);
1116}
1117
1118template <class Impl>
1119void
1120FullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid)
1121{
1122 DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
1123
1124 DPRINTF(Activity,"Activity: syscall() called.\n");
1125
1126 // Temporarily increase this by one to account for the syscall
1127 // instruction.
1128 ++(this->thread[tid]->funcExeInst);
1129
1130 // Execute the actual syscall.
1131 this->thread[tid]->syscall(callnum);
1132
1133 // Decrease funcExeInst by one as the normal commit will handle
1134 // incrementing it.
1135 --(this->thread[tid]->funcExeInst);
1136}
1137
1138template <class Impl>
1139void
1140FullO3CPU<Impl>::serializeThread(std::ostream &os, ThreadID tid)
1141{
1142 thread[tid]->serialize(os);
1143}
1144
1145template <class Impl>
1146void
1147FullO3CPU<Impl>::unserializeThread(Checkpoint *cp, const std::string &section,
1148 ThreadID tid)
1149{
1150 thread[tid]->unserialize(cp, section);
1151}
1152
1153template <class Impl>
1154unsigned int
1155FullO3CPU<Impl>::drain(DrainManager *drain_manager)
1156{
1157 // If the CPU isn't doing anything, then return immediately.
1158 if (switchedOut()) {
1159 setDrainState(Drainable::Drained);
1160 return 0;
1161 }
1162
1163 DPRINTF(Drain, "Draining...\n");
1164 setDrainState(Drainable::Draining);
1165
1166 // We only need to signal a drain to the commit stage as this
1167 // initiates squashing controls the draining. Once the commit
1168 // stage commits an instruction where it is safe to stop, it'll
1169 // squash the rest of the instructions in the pipeline and force
1170 // the fetch stage to stall. The pipeline will be drained once all
1171 // in-flight instructions have retired.
1172 commit.drain();
1173
1174 // Wake the CPU and record activity so everything can drain out if
1175 // the CPU was not able to immediately drain.
1176 if (!isDrained()) {
1177 drainManager = drain_manager;
1178
1179 wakeCPU();
1180 activityRec.activity();
1181
1182 DPRINTF(Drain, "CPU not drained\n");
1183
1184 return 1;
1185 } else {
1186 setDrainState(Drainable::Drained);
1187 DPRINTF(Drain, "CPU is already drained\n");
1188 if (tickEvent.scheduled())
1189 deschedule(tickEvent);
1190
1191 // Flush out any old data from the time buffers. In
1192 // particular, there might be some data in flight from the
1193 // fetch stage that isn't visible in any of the CPU buffers we
1194 // test in isDrained().
1195 for (int i = 0; i < timeBuffer.getSize(); ++i) {
1196 timeBuffer.advance();
1197 fetchQueue.advance();
1198 decodeQueue.advance();
1199 renameQueue.advance();
1200 iewQueue.advance();
1201 }
1202
1203 drainSanityCheck();
1204 return 0;
1205 }
1206}
1207
1208template <class Impl>
1209bool
1210FullO3CPU<Impl>::tryDrain()
1211{
1212 if (!drainManager || !isDrained())
1213 return false;
1214
1215 if (tickEvent.scheduled())
1216 deschedule(tickEvent);
1217
1218 DPRINTF(Drain, "CPU done draining, processing drain event\n");
1219 drainManager->signalDrainDone();
1220 drainManager = NULL;
1221
1222 return true;
1223}
1224
1225template <class Impl>
1226void
1227FullO3CPU<Impl>::drainSanityCheck() const
1228{
1229 assert(isDrained());
1230 fetch.drainSanityCheck();
1231 decode.drainSanityCheck();
1232 rename.drainSanityCheck();
1233 iew.drainSanityCheck();
1234 commit.drainSanityCheck();
1235}
1236
1237template <class Impl>
1238bool
1239FullO3CPU<Impl>::isDrained() const
1240{
1241 bool drained(true);
1242
1243 for (ThreadID i = 0; i < thread.size(); ++i) {
1244 if (activateThreadEvent[i].scheduled()) {
1245 DPRINTF(Drain, "CPU not drained, tread %i has a "
1246 "pending activate event\n", i);
1247 drained = false;
1248 }
1249 if (deallocateContextEvent[i].scheduled()) {
1250 DPRINTF(Drain, "CPU not drained, tread %i has a "
1251 "pending deallocate context event\n", i);
1252 drained = false;
1253 }
1254 }
1255
1256 if (!instList.empty() || !removeList.empty()) {
1257 DPRINTF(Drain, "Main CPU structures not drained.\n");
1258 drained = false;
1259 }
1260
1261 if (!fetch.isDrained()) {
1262 DPRINTF(Drain, "Fetch not drained.\n");
1263 drained = false;
1264 }
1265
1266 if (!decode.isDrained()) {
1267 DPRINTF(Drain, "Decode not drained.\n");
1268 drained = false;
1269 }
1270
1271 if (!rename.isDrained()) {
1272 DPRINTF(Drain, "Rename not drained.\n");
1273 drained = false;
1274 }
1275
1276 if (!iew.isDrained()) {
1277 DPRINTF(Drain, "IEW not drained.\n");
1278 drained = false;
1279 }
1280
1281 if (!commit.isDrained()) {
1282 DPRINTF(Drain, "Commit not drained.\n");
1283 drained = false;
1284 }
1285
1286 return drained;
1287}
1288
1289template <class Impl>
1290void
1291FullO3CPU<Impl>::commitDrained(ThreadID tid)
1292{
1293 fetch.drainStall(tid);
1294}
1295
1296template <class Impl>
1297void
1298FullO3CPU<Impl>::drainResume()
1299{
1300 setDrainState(Drainable::Running);
1301 if (switchedOut())
1302 return;
1303
1304 DPRINTF(Drain, "Resuming...\n");
1305 verifyMemoryMode();
1306
1307 fetch.drainResume();
1308 commit.drainResume();
1309
1310 _status = Idle;
1311 for (ThreadID i = 0; i < thread.size(); i++) {
1312 if (thread[i]->status() == ThreadContext::Active) {
1313 DPRINTF(Drain, "Activating thread: %i\n", i);
1314 activateThread(i);
1315 _status = Running;
1316 }
1317 }
1318
1319 assert(!tickEvent.scheduled());
1320 if (_status == Running)
1321 schedule(tickEvent, nextCycle());
1322}
1323
1324template <class Impl>
1325void
1326FullO3CPU<Impl>::switchOut()
1327{
1328 DPRINTF(O3CPU, "Switching out\n");
1329 BaseCPU::switchOut();
1330
1331 activityRec.reset();
1332
1333 _status = SwitchedOut;
1334
1335 if (checker)
1336 checker->switchOut();
1337}
1338
1339template <class Impl>
1340void
1341FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
1342{
1343 BaseCPU::takeOverFrom(oldCPU);
1344
1345 fetch.takeOverFrom();
1346 decode.takeOverFrom();
1347 rename.takeOverFrom();
1348 iew.takeOverFrom();
1349 commit.takeOverFrom();
1350
1351 assert(!tickEvent.scheduled());
1352
1353 FullO3CPU<Impl> *oldO3CPU = dynamic_cast<FullO3CPU<Impl>*>(oldCPU);
1354 if (oldO3CPU)
1355 globalSeqNum = oldO3CPU->globalSeqNum;
1356
1357 lastRunningCycle = curCycle();
1358 _status = Idle;
1359}
1360
1361template <class Impl>
1362void
1363FullO3CPU<Impl>::verifyMemoryMode() const
1364{
1365 if (!system->isTimingMode()) {
1366 fatal("The O3 CPU requires the memory system to be in "
1367 "'timing' mode.\n");
1368 }
1369}
1370
1371template <class Impl>
1372TheISA::MiscReg
1373FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid)
1374{
1375 return this->isa[tid]->readMiscRegNoEffect(misc_reg);
1376}
1377
1378template <class Impl>
1379TheISA::MiscReg
1380FullO3CPU<Impl>::readMiscReg(int misc_reg, ThreadID tid)
1381{
1382 miscRegfileReads++;
1383 return this->isa[tid]->readMiscReg(misc_reg, tcBase(tid));
1384}
1385
1386template <class Impl>
1387void
1388FullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg,
1389 const TheISA::MiscReg &val, ThreadID tid)
1390{
1391 this->isa[tid]->setMiscRegNoEffect(misc_reg, val);
1392}
1393
1394template <class Impl>
1395void
1396FullO3CPU<Impl>::setMiscReg(int misc_reg,
1397 const TheISA::MiscReg &val, ThreadID tid)
1398{
1399 miscRegfileWrites++;
1400 this->isa[tid]->setMiscReg(misc_reg, val, tcBase(tid));
1401}
1402
1403template <class Impl>
1404uint64_t
1405FullO3CPU<Impl>::readIntReg(int reg_idx)
1406{
1407 intRegfileReads++;
1408 return regFile.readIntReg(reg_idx);
1409}
1410
1411template <class Impl>
1412FloatReg
1413FullO3CPU<Impl>::readFloatReg(int reg_idx)
1414{
1415 fpRegfileReads++;
1416 return regFile.readFloatReg(reg_idx);
1417}
1418
1419template <class Impl>
1420FloatRegBits
1421FullO3CPU<Impl>::readFloatRegBits(int reg_idx)
1422{
1423 fpRegfileReads++;
1424 return regFile.readFloatRegBits(reg_idx);
1425}
1426
1427template <class Impl>
1428CCReg
1429FullO3CPU<Impl>::readCCReg(int reg_idx)
1430{
1431 ccRegfileReads++;
1432 return regFile.readCCReg(reg_idx);
1433}
1434
1435template <class Impl>
1436void
1437FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
1438{
1439 intRegfileWrites++;
1440 regFile.setIntReg(reg_idx, val);
1441}
1442
1443template <class Impl>
1444void
1445FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val)
1446{
1447 fpRegfileWrites++;
1448 regFile.setFloatReg(reg_idx, val);
1449}
1450
1451template <class Impl>
1452void
1453FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
1454{
1455 fpRegfileWrites++;
1456 regFile.setFloatRegBits(reg_idx, val);
1457}
1458
1459template <class Impl>
1460void
1461FullO3CPU<Impl>::setCCReg(int reg_idx, CCReg val)
1462{
1463 ccRegfileWrites++;
1464 regFile.setCCReg(reg_idx, val);
1465}
1466
1467template <class Impl>
1468uint64_t
1469FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid)
1470{
1471 intRegfileReads++;
1472 PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx);
1473
1474 return regFile.readIntReg(phys_reg);
1475}
1476
1477template <class Impl>
1478float
1479FullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid)
1480{
1481 fpRegfileReads++;
1482 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
1483
1484 return regFile.readFloatReg(phys_reg);
1485}
1486
1487template <class Impl>
1488uint64_t
1489FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid)
1490{
1491 fpRegfileReads++;
1492 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
1493
1494 return regFile.readFloatRegBits(phys_reg);
1495}
1496
1497template <class Impl>
1498CCReg
1499FullO3CPU<Impl>::readArchCCReg(int reg_idx, ThreadID tid)
1500{
1501 ccRegfileReads++;
1502 PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx);
1503
1504 return regFile.readCCReg(phys_reg);
1505}
1506
1507template <class Impl>
1508void
1509FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid)
1510{
1511 intRegfileWrites++;
1512 PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx);
1513
1514 regFile.setIntReg(phys_reg, val);
1515}
1516
1517template <class Impl>
1518void
1519FullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid)
1520{
1521 fpRegfileWrites++;
1522 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
1523
1524 regFile.setFloatReg(phys_reg, val);
1525}
1526
1527template <class Impl>
1528void
1529FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid)
1530{
1531 fpRegfileWrites++;
1532 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx);
1533
1534 regFile.setFloatRegBits(phys_reg, val);
1535}
1536
1537template <class Impl>
1538void
1539FullO3CPU<Impl>::setArchCCReg(int reg_idx, CCReg val, ThreadID tid)
1540{
1541 ccRegfileWrites++;
1542 PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx);
1543
1544 regFile.setCCReg(phys_reg, val);
1545}
1546
1547template <class Impl>
1548TheISA::PCState
1549FullO3CPU<Impl>::pcState(ThreadID tid)
1550{
1551 return commit.pcState(tid);
1552}
1553
1554template <class Impl>
1555void
1556FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid)
1557{
1558 commit.pcState(val, tid);
1559}
1560
1561template <class Impl>
1562Addr
1563FullO3CPU<Impl>::instAddr(ThreadID tid)
1564{
1565 return commit.instAddr(tid);
1566}
1567
1568template <class Impl>
1569Addr
1570FullO3CPU<Impl>::nextInstAddr(ThreadID tid)
1571{
1572 return commit.nextInstAddr(tid);
1573}
1574
1575template <class Impl>
1576MicroPC
1577FullO3CPU<Impl>::microPC(ThreadID tid)
1578{
1579 return commit.microPC(tid);
1580}
1581
1582template <class Impl>
1583void
1584FullO3CPU<Impl>::squashFromTC(ThreadID tid)
1585{
1586 this->thread[tid]->noSquashFromTC = true;
1587 this->commit.generateTCEvent(tid);
1588}
1589
1590template <class Impl>
1591typename FullO3CPU<Impl>::ListIt
1592FullO3CPU<Impl>::addInst(DynInstPtr &inst)
1593{
1594 instList.push_back(inst);
1595
1596 return --(instList.end());
1597}
1598
1599template <class Impl>
1600void
1601FullO3CPU<Impl>::instDone(ThreadID tid, DynInstPtr &inst)
1602{
1603 // Keep an instruction count.
1604 if (!inst->isMicroop() || inst->isLastMicroop()) {
1605 thread[tid]->numInst++;
1606 thread[tid]->numInsts++;
1607 committedInsts[tid]++;
1608 }
1609 thread[tid]->numOp++;
1610 thread[tid]->numOps++;
1611 committedOps[tid]++;
1612
1613 system->totalNumInsts++;
1614 // Check for instruction-count-based events.
1615 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
1616 system->instEventQueue.serviceEvents(system->totalNumInsts);
1617}
1618
1619template <class Impl>
1620void
1621FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
1622{
1623 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s "
1624 "[sn:%lli]\n",
1625 inst->threadNumber, inst->pcState(), inst->seqNum);
1626
1627 removeInstsThisCycle = true;
1628
1629 // Remove the front instruction.
1630 removeList.push(inst->getInstListIt());
1631}
1632
1633template <class Impl>
1634void
1635FullO3CPU<Impl>::removeInstsNotInROB(ThreadID tid)
1636{
1637 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction"
1638 " list.\n", tid);
1639
1640 ListIt end_it;
1641
1642 bool rob_empty = false;
1643
1644 if (instList.empty()) {
1645 return;
1646 } else if (rob.isEmpty(tid)) {
1647 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n");
1648 end_it = instList.begin();
1649 rob_empty = true;
1650 } else {
1651 end_it = (rob.readTailInst(tid))->getInstListIt();
1652 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n");
1653 }
1654
1655 removeInstsThisCycle = true;
1656
1657 ListIt inst_it = instList.end();
1658
1659 inst_it--;
1660
1661 // Walk through the instruction list, removing any instructions
1662 // that were inserted after the given instruction iterator, end_it.
1663 while (inst_it != end_it) {
1664 assert(!instList.empty());
1665
1666 squashInstIt(inst_it, tid);
1667
1668 inst_it--;
1669 }
1670
1671 // If the ROB was empty, then we actually need to remove the first
1672 // instruction as well.
1673 if (rob_empty) {
1674 squashInstIt(inst_it, tid);
1675 }
1676}
1677
1678template <class Impl>
1679void
1680FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid)
1681{
1682 assert(!instList.empty());
1683
1684 removeInstsThisCycle = true;
1685
1686 ListIt inst_iter = instList.end();
1687
1688 inst_iter--;
1689
1690 DPRINTF(O3CPU, "Deleting instructions from instruction "
1691 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1692 tid, seq_num, (*inst_iter)->seqNum);
1693
1694 while ((*inst_iter)->seqNum > seq_num) {
1695
1696 bool break_loop = (inst_iter == instList.begin());
1697
1698 squashInstIt(inst_iter, tid);
1699
1700 inst_iter--;
1701
1702 if (break_loop)
1703 break;
1704 }
1705}
1706
1707template <class Impl>
1708inline void
1709FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid)
1710{
1711 if ((*instIt)->threadNumber == tid) {
1712 DPRINTF(O3CPU, "Squashing instruction, "
1713 "[tid:%i] [sn:%lli] PC %s\n",
1714 (*instIt)->threadNumber,
1715 (*instIt)->seqNum,
1716 (*instIt)->pcState());
1717
1718 // Mark it as squashed.
1719 (*instIt)->setSquashed();
1720
1721 // @todo: Formulate a consistent method for deleting
1722 // instructions from the instruction list
1723 // Remove the instruction from the list.
1724 removeList.push(instIt);
1725 }
1726}
1727
1728template <class Impl>
1729void
1730FullO3CPU<Impl>::cleanUpRemovedInsts()
1731{
1732 while (!removeList.empty()) {
1733 DPRINTF(O3CPU, "Removing instruction, "
1734 "[tid:%i] [sn:%lli] PC %s\n",
1735 (*removeList.front())->threadNumber,
1736 (*removeList.front())->seqNum,
1737 (*removeList.front())->pcState());
1738
1739 instList.erase(removeList.front());
1740
1741 removeList.pop();
1742 }
1743
1744 removeInstsThisCycle = false;
1745}
1746/*
1747template <class Impl>
1748void
1749FullO3CPU<Impl>::removeAllInsts()
1750{
1751 instList.clear();
1752}
1753*/
1754template <class Impl>
1755void
1756FullO3CPU<Impl>::dumpInsts()
1757{
1758 int num = 0;
1759
1760 ListIt inst_list_it = instList.begin();
1761
1762 cprintf("Dumping Instruction List\n");
1763
1764 while (inst_list_it != instList.end()) {
1765 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1766 "Squashed:%i\n\n",
1767 num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber,
1768 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
1769 (*inst_list_it)->isSquashed());
1770 inst_list_it++;
1771 ++num;
1772 }
1773}
1774/*
1775template <class Impl>
1776void
1777FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
1778{
1779 iew.wakeDependents(inst);
1780}
1781*/
1782template <class Impl>
1783void
1784FullO3CPU<Impl>::wakeCPU()
1785{
1786 if (activityRec.active() || tickEvent.scheduled()) {
1787 DPRINTF(Activity, "CPU already running.\n");
1788 return;
1789 }
1790
1791 DPRINTF(Activity, "Waking up CPU\n");
1792
1793 Cycles cycles(curCycle() - lastRunningCycle);
1794 // @todo: This is an oddity that is only here to match the stats
1795 if (cycles != 0)
1796 --cycles;
1797 idleCycles += cycles;
1798 numCycles += cycles;
1799
1800 schedule(tickEvent, clockEdge());
1801}
1802
1803template <class Impl>
1804void
1805FullO3CPU<Impl>::wakeup()
1806{
1807 if (this->thread[0]->status() != ThreadContext::Suspended)
1808 return;
1809
1810 this->wakeCPU();
1811
1812 DPRINTF(Quiesce, "Suspended Processor woken\n");
1813 this->threadContexts[0]->activate();
1814}
1815
1816template <class Impl>
1817ThreadID
1818FullO3CPU<Impl>::getFreeTid()
1819{
1820 for (ThreadID tid = 0; tid < numThreads; tid++) {
1821 if (!tids[tid]) {
1822 tids[tid] = true;
1823 return tid;
1824 }
1825 }
1826
1827 return InvalidThreadID;
1828}
1829
1830template <class Impl>
1831void
1832FullO3CPU<Impl>::doContextSwitch()
1833{
1834 if (contextSwitch) {
1835
1836 //ADD CODE TO DEACTIVE THREAD HERE (???)
1837
1838 ThreadID size = cpuWaitList.size();
1839 for (ThreadID tid = 0; tid < size; tid++) {
1840 activateWhenReady(tid);
1841 }
1842
1843 if (cpuWaitList.size() == 0)
1844 contextSwitch = true;
1845 }
1846}
1847
1848template <class Impl>
1849void
1850FullO3CPU<Impl>::updateThreadPriority()
1851{
1852 if (activeThreads.size() > 1) {
1853 //DEFAULT TO ROUND ROBIN SCHEME
1854 //e.g. Move highest priority to end of thread list
1855 list<ThreadID>::iterator list_begin = activeThreads.begin();
1856
1857 unsigned high_thread = *list_begin;
1858
1859 activeThreads.erase(list_begin);
1860
1861 activeThreads.push_back(high_thread);
1862 }
1863}
1864
1865// Forward declaration of FullO3CPU.
1866template class FullO3CPU<O3CPUImpl>;