cpu.cc (2873:1377a68cd00e) cpu.cc (2875:9b6f6b75b187)
1/*
2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;

--- 101 unchanged lines hidden (view full) ---

110template <class Impl>
111const char *
112FullO3CPU<Impl>::ActivateThreadEvent::description()
113{
114 return "FullO3CPU \"Activate Thread\" event";
115}
116
117template <class Impl>
1/*
2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;

--- 101 unchanged lines hidden (view full) ---

110template <class Impl>
111const char *
112FullO3CPU<Impl>::ActivateThreadEvent::description()
113{
114 return "FullO3CPU \"Activate Thread\" event";
115}
116
117template <class Impl>
118FullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent()
119 : Event(&mainEventQueue, CPU_Tick_Pri)
120{
121}
122
123template <class Impl>
124void
125FullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num,
126 FullO3CPU<Impl> *thread_cpu)
127{
128 tid = thread_num;
129 cpu = thread_cpu;
130}
131
132template <class Impl>
133void
134FullO3CPU<Impl>::DeallocateContextEvent::process()
135{
136 cpu->deactivateThread(tid);
137 cpu->removeThread(tid);
138}
139
140template <class Impl>
141const char *
142FullO3CPU<Impl>::DeallocateContextEvent::description()
143{
144 return "FullO3CPU \"Deallocate Context\" event";
145}
146
147template <class Impl>
118FullO3CPU<Impl>::FullO3CPU(Params *params)
119 : BaseO3CPU(params),
120 tickEvent(this),
121 removeInstsThisCycle(false),
122 fetch(params),
123 decode(params),
124 rename(params),
125 iew(params),

--- 10 unchanged lines hidden (view full) ---

136 params->numberOfThreads),
137
138 scoreboard(params->numberOfThreads,
139 TheISA::NumIntRegs, params->numPhysIntRegs,
140 TheISA::NumFloatRegs, params->numPhysFloatRegs,
141 TheISA::NumMiscRegs * number_of_threads,
142 TheISA::ZeroReg),
143
148FullO3CPU<Impl>::FullO3CPU(Params *params)
149 : BaseO3CPU(params),
150 tickEvent(this),
151 removeInstsThisCycle(false),
152 fetch(params),
153 decode(params),
154 rename(params),
155 iew(params),

--- 10 unchanged lines hidden (view full) ---

166 params->numberOfThreads),
167
168 scoreboard(params->numberOfThreads,
169 TheISA::NumIntRegs, params->numPhysIntRegs,
170 TheISA::NumFloatRegs, params->numPhysFloatRegs,
171 TheISA::NumMiscRegs * number_of_threads,
172 TheISA::ZeroReg),
173
144 timeBuffer(params->backComSize, params->forwardComSize),
145 fetchQueue(params->backComSize, params->forwardComSize),
146 decodeQueue(params->backComSize, params->forwardComSize),
147 renameQueue(params->backComSize, params->forwardComSize),
148 iewQueue(params->backComSize, params->forwardComSize),
149 activityRec(NumStages,
150 params->backComSize + params->forwardComSize,
151 params->activity),
174 // For now just have these time buffers be pretty big.
175 // @todo: Make these time buffer sizes parameters or derived
176 // from latencies
177 timeBuffer(5, 5),
178 fetchQueue(5, 5),
179 decodeQueue(5, 5),
180 renameQueue(5, 5),
181 iewQueue(5, 5),
182 activityRec(NumStages, 10, params->activity),
152
153 globalSeqNum(1),
154
155#if FULL_SYSTEM
156 system(params->system),
157 physmem(system->physmem),
158#endif // FULL_SYSTEM
159 mem(params->mem),
183
184 globalSeqNum(1),
185
186#if FULL_SYSTEM
187 system(params->system),
188 physmem(system->physmem),
189#endif // FULL_SYSTEM
190 mem(params->mem),
160 drainCount(0),
191 switchCount(0),
161 deferRegistration(params->deferRegistration),
162 numThreads(number_of_threads)
163{
164 _status = Idle;
165
166 checker = NULL;
167
168 if (params->checker) {

--- 39 unchanged lines hidden (view full) ---

208 decode.setDecodeQueue(&decodeQueue);
209 rename.setDecodeQueue(&decodeQueue);
210 rename.setRenameQueue(&renameQueue);
211 iew.setRenameQueue(&renameQueue);
212 iew.setIEWQueue(&iewQueue);
213 commit.setIEWQueue(&iewQueue);
214 commit.setRenameQueue(&renameQueue);
215
192 deferRegistration(params->deferRegistration),
193 numThreads(number_of_threads)
194{
195 _status = Idle;
196
197 checker = NULL;
198
199 if (params->checker) {

--- 39 unchanged lines hidden (view full) ---

239 decode.setDecodeQueue(&decodeQueue);
240 rename.setDecodeQueue(&decodeQueue);
241 rename.setRenameQueue(&renameQueue);
242 iew.setRenameQueue(&renameQueue);
243 iew.setIEWQueue(&iewQueue);
244 commit.setIEWQueue(&iewQueue);
245 commit.setRenameQueue(&renameQueue);
246
247 commit.setFetchStage(&fetch);
216 commit.setIEWStage(&iew);
217 rename.setIEWStage(&iew);
218 rename.setCommitStage(&commit);
219
220#if !FULL_SYSTEM
221 int active_threads = params->workload.size();
222
223 if (active_threads > Impl::MaxThreads) {

--- 130 unchanged lines hidden (view full) ---

354 .name(name() + ".ipc_total")
355 .desc("IPC: Total IPC of All Threads")
356 .precision(6);
357 totalIpc = totalCommittedInsts / simTicks;
358
359}
360
361template <class Impl>
248 commit.setIEWStage(&iew);
249 rename.setIEWStage(&iew);
250 rename.setCommitStage(&commit);
251
252#if !FULL_SYSTEM
253 int active_threads = params->workload.size();
254
255 if (active_threads > Impl::MaxThreads) {

--- 130 unchanged lines hidden (view full) ---

386 .name(name() + ".ipc_total")
387 .desc("IPC: Total IPC of All Threads")
388 .precision(6);
389 totalIpc = totalCommittedInsts / simTicks;
390
391}
392
393template <class Impl>
362Port *
363FullO3CPU<Impl>::getPort(const std::string &if_name, int idx)
364{
365 if (if_name == "dcache_port")
366 return iew.getDcachePort();
367 else if (if_name == "icache_port")
368 return fetch.getIcachePort();
369 else
370 panic("No Such Port\n");
371}
372
373template <class Impl>
374void
375FullO3CPU<Impl>::tick()
376{
377 DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
378
379 ++numCycles;
380
381// activity = false;

--- 23 unchanged lines hidden (view full) ---

405
406 activityRec.advance();
407
408 if (removeInstsThisCycle) {
409 cleanUpRemovedInsts();
410 }
411
412 if (!tickEvent.scheduled()) {
394void
395FullO3CPU<Impl>::tick()
396{
397 DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
398
399 ++numCycles;
400
401// activity = false;

--- 23 unchanged lines hidden (view full) ---

425
426 activityRec.advance();
427
428 if (removeInstsThisCycle) {
429 cleanUpRemovedInsts();
430 }
431
432 if (!tickEvent.scheduled()) {
413 if (_status == SwitchedOut ||
414 getState() == SimObject::DrainedTiming) {
433 if (_status == SwitchedOut) {
415 // increment stat
416 lastRunningCycle = curTick;
417 } else if (!activityRec.active()) {
418 lastRunningCycle = curTick;
419 timesIdled++;
420 } else {
421 tickEvent.schedule(curTick + cycles(1));
422 }

--- 44 unchanged lines hidden (view full) ---

467 rename.initStage();
468 commit.initStage();
469
470 commit.setThreads(thread);
471}
472
473template <class Impl>
474void
434 // increment stat
435 lastRunningCycle = curTick;
436 } else if (!activityRec.active()) {
437 lastRunningCycle = curTick;
438 timesIdled++;
439 } else {
440 tickEvent.schedule(curTick + cycles(1));
441 }

--- 44 unchanged lines hidden (view full) ---

486 rename.initStage();
487 commit.initStage();
488
489 commit.setThreads(thread);
490}
491
492template <class Impl>
493void
494FullO3CPU<Impl>::activateThread(unsigned tid)
495{
496 list<unsigned>::iterator isActive = find(
497 activeThreads.begin(), activeThreads.end(), tid);
498
499 if (isActive == activeThreads.end()) {
500 DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n",
501 tid);
502
503 activeThreads.push_back(tid);
504 }
505}
506
507template <class Impl>
508void
509FullO3CPU<Impl>::deactivateThread(unsigned tid)
510{
511 //Remove From Active List, if Active
512 list<unsigned>::iterator thread_it =
513 find(activeThreads.begin(), activeThreads.end(), tid);
514
515 if (thread_it != activeThreads.end()) {
516 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
517 tid);
518 activeThreads.erase(thread_it);
519 }
520}
521
522template <class Impl>
523void
524FullO3CPU<Impl>::activateContext(int tid, int delay)
525{
526 // Needs to set each stage to running as well.
527 if (delay){
528 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate "
529 "on cycle %d\n", tid, curTick + cycles(delay));
530 scheduleActivateThreadEvent(tid, delay);
531 } else {
532 activateThread(tid);
533 }
534
535 if(lastActivatedCycle < curTick) {
536 scheduleTickEvent(delay);
537
538 // Be sure to signal that there's some activity so the CPU doesn't
539 // deschedule itself.
540 activityRec.activity();
541 fetch.wakeFromQuiesce();
542
543 lastActivatedCycle = curTick;
544
545 _status = Running;
546 }
547}
548
549template <class Impl>
550void
551FullO3CPU<Impl>::deallocateContext(int tid, int delay)
552{
553 // Schedule removal of thread data from CPU
554 if (delay){
555 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate "
556 "on cycle %d\n", tid, curTick + cycles(delay));
557 scheduleDeallocateContextEvent(tid, delay);
558 } else {
559 deactivateThread(tid);
560 removeThread(tid);
561 }
562}
563
564template <class Impl>
565void
566FullO3CPU<Impl>::suspendContext(int tid)
567{
568 DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
569 unscheduleTickEvent();
570 _status = Idle;
571/*
572 //Remove From Active List, if Active
573 list<unsigned>::iterator isActive = find(
574 activeThreads.begin(), activeThreads.end(), tid);
575
576 if (isActive != activeThreads.end()) {
577 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
578 tid);
579 activeThreads.erase(isActive);
580 }
581*/
582}
583
584template <class Impl>
585void
586FullO3CPU<Impl>::haltContext(int tid)
587{
588 DPRINTF(O3CPU,"[tid:%i]: Halting Thread Context", tid);
589/*
590 //Remove From Active List, if Active
591 list<unsigned>::iterator isActive = find(
592 activeThreads.begin(), activeThreads.end(), tid);
593
594 if (isActive != activeThreads.end()) {
595 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
596 tid);
597 activeThreads.erase(isActive);
598
599 removeThread(tid);
600 }
601*/
602}
603
604template <class Impl>
605void
475FullO3CPU<Impl>::insertThread(unsigned tid)
476{
477 DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU");
478 // Will change now that the PC and thread state is internal to the CPU
479 // and not in the ThreadContext.
480#if FULL_SYSTEM
481 ThreadContext *src_tc = system->threadContexts[tid];
482#else

--- 34 unchanged lines hidden (view full) ---

517 commit.rob->resetEntries();
518 iew.resetEntries();
519}
520
521template <class Impl>
522void
523FullO3CPU<Impl>::removeThread(unsigned tid)
524{
606FullO3CPU<Impl>::insertThread(unsigned tid)
607{
608 DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU");
609 // Will change now that the PC and thread state is internal to the CPU
610 // and not in the ThreadContext.
611#if FULL_SYSTEM
612 ThreadContext *src_tc = system->threadContexts[tid];
613#else

--- 34 unchanged lines hidden (view full) ---

648 commit.rob->resetEntries();
649 iew.resetEntries();
650}
651
652template <class Impl>
653void
654FullO3CPU<Impl>::removeThread(unsigned tid)
655{
525 DPRINTF(O3CPU,"[tid:%i] Removing thread from CPU.");
656 DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.");
526
527 // Copy Thread Data From RegFile
528 // If thread is suspended, it might be re-allocated
529 //this->copyToTC(tid);
530
531 // Unbind Int Regs from Rename Map
532 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
533 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);

--- 9 unchanged lines hidden (view full) ---

543 scoreboard.unsetReg(phys_reg);
544 freeList.addReg(phys_reg);
545 }
546
547 // Squash Throughout Pipeline
548 fetch.squash(0,tid);
549 decode.squash(tid);
550 rename.squash(tid);
657
658 // Copy Thread Data From RegFile
659 // If thread is suspended, it might be re-allocated
660 //this->copyToTC(tid);
661
662 // Unbind Int Regs from Rename Map
663 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
664 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);

--- 9 unchanged lines hidden (view full) ---

674 scoreboard.unsetReg(phys_reg);
675 freeList.addReg(phys_reg);
676 }
677
678 // Squash Throughout Pipeline
679 fetch.squash(0,tid);
680 decode.squash(tid);
681 rename.squash(tid);
682 iew.squash(tid);
683 commit.rob->squash(commit.rob->readHeadInst(tid)->seqNum, tid);
551
552 assert(iew.ldstQueue.getCount(tid) == 0);
553
554 // Reset ROB/IQ/LSQ Entries
555 if (activeThreads.size() >= 1) {
556 commit.rob->resetEntries();
557 iew.resetEntries();
558 }

--- 47 unchanged lines hidden (view full) ---

606
607 cpuWaitList.remove(tid);
608 } else {
609 suspendContext(tid);
610
611 //blocks fetch
612 contextSwitch = true;
613
684
685 assert(iew.ldstQueue.getCount(tid) == 0);
686
687 // Reset ROB/IQ/LSQ Entries
688 if (activeThreads.size() >= 1) {
689 commit.rob->resetEntries();
690 iew.resetEntries();
691 }

--- 47 unchanged lines hidden (view full) ---

739
740 cpuWaitList.remove(tid);
741 } else {
742 suspendContext(tid);
743
744 //blocks fetch
745 contextSwitch = true;
746
747 //@todo: dont always add to waitlist
614 //do waitlist
615 cpuWaitList.push_back(tid);
616 }
617}
618
619template <class Impl>
620void
748 //do waitlist
749 cpuWaitList.push_back(tid);
750 }
751}
752
753template <class Impl>
754void
621FullO3CPU<Impl>::activateThread(unsigned int tid)
755FullO3CPU<Impl>::switchOut()
622{
756{
623 list<unsigned>::iterator isActive = find(
624 activeThreads.begin(), activeThreads.end(), tid);
757 switchCount = 0;
758 fetch.switchOut();
759 decode.switchOut();
760 rename.switchOut();
761 iew.switchOut();
762 commit.switchOut();
625
763
626 if (isActive == activeThreads.end()) {
627 DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n",
628 tid);
629
630 activeThreads.push_back(tid);
631 }
632}
633
634
635template <class Impl>
636void
637FullO3CPU<Impl>::activateContext(int tid, int delay)
638{
639 // Needs to set each stage to running as well.
640 if (delay){
641 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate "
642 "on cycle %d\n", tid, curTick + cycles(delay));
643 scheduleActivateThreadEvent(tid, delay);
644 } else {
645 activateThread(tid);
646 }
647
648 if(lastActivatedCycle < curTick) {
649 scheduleTickEvent(delay);
650
651 // Be sure to signal that there's some activity so the CPU doesn't
652 // deschedule itself.
653 activityRec.activity();
654 fetch.wakeFromQuiesce();
655
656 lastActivatedCycle = curTick;
657
658 _status = Running;
659 }
660}
661
662template <class Impl>
663void
664FullO3CPU<Impl>::suspendContext(int tid)
665{
666 DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
667 unscheduleTickEvent();
668 _status = Idle;
669/*
670 //Remove From Active List, if Active
671 list<unsigned>::iterator isActive = find(
672 activeThreads.begin(), activeThreads.end(), tid);
673
674 if (isActive != activeThreads.end()) {
675 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
676 tid);
677 activeThreads.erase(isActive);
678 }
679*/
680}
681
682template <class Impl>
683void
684FullO3CPU<Impl>::deallocateContext(int tid)
685{
686 DPRINTF(O3CPU,"[tid:%i]: Deallocating Thread Context", tid);
687
688 //Remove From Active List, if Active
689 list<unsigned>::iterator thread_it =
690 find(activeThreads.begin(), activeThreads.end(), tid);
691
692 if (thread_it != activeThreads.end()) {
693 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
694 tid);
695 activeThreads.erase(thread_it);
696
697 removeThread(tid);
698 }
699}
700
701template <class Impl>
702void
703FullO3CPU<Impl>::haltContext(int tid)
704{
705 DPRINTF(O3CPU,"[tid:%i]: Halting Thread Context", tid);
706/*
707 //Remove From Active List, if Active
708 list<unsigned>::iterator isActive = find(
709 activeThreads.begin(), activeThreads.end(), tid);
710
711 if (isActive != activeThreads.end()) {
712 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
713 tid);
714 activeThreads.erase(isActive);
715
716 removeThread(tid);
717 }
718*/
719}
720
721template <class Impl>
722void
723FullO3CPU<Impl>::serialize(std::ostream &os)
724{
725 SERIALIZE_ENUM(_status);
726 BaseCPU::serialize(os);
727 nameOut(os, csprintf("%s.tickEvent", name()));
728 tickEvent.serialize(os);
729
730 // Use SimpleThread's ability to checkpoint to make it easier to
731 // write out the registers. Also make this static so it doesn't
732 // get instantiated multiple times (causes a panic in statistics).
733 static SimpleThread temp;
734
735 for (int i = 0; i < thread.size(); i++) {
736 nameOut(os, csprintf("%s.xc.%i", name(), i));
737 temp.copyTC(thread[i]->getTC());
738 temp.serialize(os);
739 }
740}
741
742template <class Impl>
743void
744FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
745{
746 UNSERIALIZE_ENUM(_status);
747 BaseCPU::unserialize(cp, section);
748 tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
749
750 // Use SimpleThread's ability to checkpoint to make it easier to
751 // read in the registers. Also make this static so it doesn't
752 // get instantiated multiple times (causes a panic in statistics).
753 static SimpleThread temp;
754
755 for (int i = 0; i < thread.size(); i++) {
756 temp.copyTC(thread[i]->getTC());
757 temp.unserialize(cp, csprintf("%s.xc.%i", section, i));
758 thread[i]->getTC()->copyArchRegs(temp.getTC());
759 }
760}
761
762template <class Impl>
763bool
764FullO3CPU<Impl>::drain(Event *drain_event)
765{
766 drainCount = 0;
767 fetch.drain();
768 decode.drain();
769 rename.drain();
770 iew.drain();
771 commit.drain();
772
773 // Wake the CPU and record activity so everything can drain out if
764 // Wake the CPU and record activity so everything can drain out if
774 // the CPU was not able to immediately drain.
775 if (getState() != SimObject::DrainedTiming) {
776 // A bit of a hack...set the drainEvent after all the drain()
777 // calls have been made, that way if all of the stages drain
778 // immediately, the signalDrained() function knows not to call
779 // process on the drain event.
780 drainEvent = drain_event;
781
782 wakeCPU();
783 activityRec.activity();
784
785 return false;
786 } else {
787 return true;
788 }
765 // the CPU is currently idle.
766 wakeCPU();
767 activityRec.activity();
789}
790
791template <class Impl>
792void
768}
769
770template <class Impl>
771void
793FullO3CPU<Impl>::resume()
772FullO3CPU<Impl>::signalSwitched()
794{
773{
795 fetch.resume();
796 decode.resume();
797 rename.resume();
798 iew.resume();
799 commit.resume();
774 if (++switchCount == NumStages) {
775 fetch.doSwitchOut();
776 rename.doSwitchOut();
777 commit.doSwitchOut();
778 instList.clear();
779 while (!removeList.empty()) {
780 removeList.pop();
781 }
800
782
801 if (_status == SwitchedOut || _status == Idle)
802 return;
783#if USE_CHECKER
784 if (checker)
785 checker->switchOut();
786#endif
803
787
804 if (!tickEvent.scheduled())
805 tickEvent.schedule(curTick);
806 _status = Running;
807 changeState(SimObject::Timing);
808}
809
810template <class Impl>
811void
812FullO3CPU<Impl>::signalDrained()
813{
814 if (++drainCount == NumStages) {
815 if (tickEvent.scheduled())
816 tickEvent.squash();
788 if (tickEvent.scheduled())
789 tickEvent.squash();
817
818 changeState(SimObject::DrainedTiming);
819
820 if (drainEvent) {
821 drainEvent->process();
822 drainEvent = NULL;
823 }
790 _status = SwitchedOut;
824 }
791 }
825 assert(drainCount <= 5);
792 assert(switchCount <= 5);
826}
827
828template <class Impl>
829void
793}
794
795template <class Impl>
796void
830FullO3CPU<Impl>::switchOut()
831{
832 fetch.switchOut();
833 rename.switchOut();
834 commit.switchOut();
835 instList.clear();
836 while (!removeList.empty()) {
837 removeList.pop();
838 }
839
840 _status = SwitchedOut;
841#if USE_CHECKER
842 if (checker)
843 checker->switchOut();
844#endif
845}
846
847template <class Impl>
848void
849FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
850{
851 // Flush out any old data from the time buffers.
797FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
798{
799 // Flush out any old data from the time buffers.
852 for (int i = 0; i < timeBuffer.getSize(); ++i) {
800 for (int i = 0; i < 10; ++i) {
853 timeBuffer.advance();
854 fetchQueue.advance();
855 decodeQueue.advance();
856 renameQueue.advance();
857 iewQueue.advance();
858 }
859
860 activityRec.reset();

--- 493 unchanged lines hidden ---
801 timeBuffer.advance();
802 fetchQueue.advance();
803 decodeQueue.advance();
804 renameQueue.advance();
805 iewQueue.advance();
806 }
807
808 activityRec.reset();

--- 493 unchanged lines hidden ---