2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #ifndef __CPU_O3_CPU_HH__
33 #define __CPU_O3_CPU_HH__
41 #include "arch/types.hh"
42 #include "base/statistics.hh"
43 #include "base/timebuf.hh"
44 #include "config/full_system.hh"
45 #include "cpu/activity.hh"
46 #include "cpu/base.hh"
47 #include "cpu/simple_thread.hh"
48 #include "cpu/o3/comm.hh"
49 #include "cpu/o3/cpu_policy.hh"
50 #include "cpu/o3/scoreboard.hh"
51 #include "cpu/o3/thread_state.hh"
52 //#include "cpu/o3/thread_context.hh"
53 #include "sim/process.hh"
59 class O3ThreadContext;
65 class BaseO3CPU : public BaseCPU
67 //Stuff that's pretty ISA independent will go here.
69 typedef BaseCPU::Params Params;
71 BaseO3CPU(Params *params);
75 /** Sets this CPU's ID. */
76 void setCpuId(int id) { cpu_id = id; }
78 /** Reads this CPU's ID. */
79 int readCpuId() { return cpu_id; }
86 * FullO3CPU class, has each of the stages (fetch through commit)
87 * within it, as well as all of the time buffers between stages. The
88 * tick() function for the CPU is defined here.
91 class FullO3CPU : public BaseO3CPU
94 typedef TheISA::FloatReg FloatReg;
95 typedef TheISA::FloatRegBits FloatRegBits;
97 // Typedefs from the Impl here.
98 typedef typename Impl::CPUPol CPUPolicy;
99 typedef typename Impl::Params Params;
100 typedef typename Impl::DynInstPtr DynInstPtr;
102 typedef O3ThreadState<Impl> Thread;
104 typedef typename std::list<DynInstPtr>::iterator ListIt;
106 friend class O3ThreadContext<Impl>;
117 /** Overall CPU status. */
120 /** Per-thread status in CPU, used for SMT. */
121 Status _threadStatus[Impl::MaxThreads];
124 class TickEvent : public Event
127 /** Pointer to the CPU. */
128 FullO3CPU<Impl> *cpu;
131 /** Constructs a tick event. */
132 TickEvent(FullO3CPU<Impl> *c);
134 /** Processes a tick event, calling tick() on the CPU. */
136 /** Returns the description of the tick event. */
137 const char *description();
140 /** The tick event used for scheduling CPU ticks. */
143 /** Schedule tick event, regardless of its current state. */
144 void scheduleTickEvent(int delay)
146 if (tickEvent.squashed())
147 tickEvent.reschedule(curTick + cycles(delay));
148 else if (!tickEvent.scheduled())
149 tickEvent.schedule(curTick + cycles(delay));
152 /** Unschedule tick event, regardless of its current state. */
153 void unscheduleTickEvent()
155 if (tickEvent.scheduled())
159 class ActivateThreadEvent : public Event
162 /** Number of Thread to Activate */
165 /** Pointer to the CPU. */
166 FullO3CPU<Impl> *cpu;
169 /** Constructs the event. */
170 ActivateThreadEvent();
172 /** Initialize Event */
173 void init(int thread_num, FullO3CPU<Impl> *thread_cpu);
175 /** Processes the event, calling activateThread() on the CPU. */
178 /** Returns the description of the event. */
179 const char *description();
182 /** Schedule thread to activate , regardless of its current state. */
183 void scheduleActivateThreadEvent(int tid, int delay)
185 // Schedule thread to activate, regardless of its current state.
186 if (activateThreadEvent[tid].squashed())
187 activateThreadEvent[tid].reschedule(curTick + cycles(delay));
188 else if (!activateThreadEvent[tid].scheduled())
189 activateThreadEvent[tid].schedule(curTick + cycles(delay));
192 /** Unschedule actiavte thread event, regardless of its current state. */
193 void unscheduleActivateThreadEvent(int tid)
195 if (activateThreadEvent[tid].scheduled())
196 activateThreadEvent[tid].squash();
199 /** The tick event used for scheduling CPU ticks. */
200 ActivateThreadEvent activateThreadEvent[Impl::MaxThreads];
202 class DeallocateContextEvent : public Event
205 /** Number of Thread to deactivate */
208 /** Should the thread be removed from the CPU? */
211 /** Pointer to the CPU. */
212 FullO3CPU<Impl> *cpu;
215 /** Constructs the event. */
216 DeallocateContextEvent();
218 /** Initialize Event */
219 void init(int thread_num, FullO3CPU<Impl> *thread_cpu);
221 /** Processes the event, calling activateThread() on the CPU. */
224 /** Sets whether the thread should also be removed from the CPU. */
225 void setRemove(bool _remove) { remove = _remove; }
227 /** Returns the description of the event. */
228 const char *description();
231 /** Schedule cpu to deallocate thread context.*/
232 void scheduleDeallocateContextEvent(int tid, bool remove, int delay)
234 // Schedule thread to activate, regardless of its current state.
235 if (deallocateContextEvent[tid].squashed())
236 deallocateContextEvent[tid].reschedule(curTick + cycles(delay));
237 else if (!deallocateContextEvent[tid].scheduled())
238 deallocateContextEvent[tid].schedule(curTick + cycles(delay));
241 /** Unschedule thread deallocation in CPU */
242 void unscheduleDeallocateContextEvent(int tid)
244 if (deallocateContextEvent[tid].scheduled())
245 deallocateContextEvent[tid].squash();
248 /** The tick event used for scheduling CPU ticks. */
249 DeallocateContextEvent deallocateContextEvent[Impl::MaxThreads];
252 /** Constructs a CPU with the given parameters. */
253 FullO3CPU(Params *params);
257 /** Registers statistics. */
258 void fullCPURegStats();
260 /** Returns a specific port. */
261 Port *getPort(const std::string &if_name, int idx);
263 /** Ticks CPU, calling tick() on each stage, and checking the overall
264 * activity to see if the CPU should deschedule itself.
268 /** Initialize the CPU */
271 /** Returns the Number of Active Threads in the CPU */
272 int numActiveThreads()
273 { return activeThreads.size(); }
275 /** Add Thread to Active Threads List */
276 void activateThread(unsigned tid);
278 /** Remove Thread from Active Threads List */
279 void deactivateThread(unsigned tid);
281 /** Setup CPU to insert a thread's context */
282 void insertThread(unsigned tid);
284 /** Remove all of a thread's context from CPU */
285 void removeThread(unsigned tid);
287 /** Count the Total Instructions Committed in the CPU. */
288 virtual Counter totalInstructions() const
292 for (int i=0; i < thread.size(); i++)
293 total += thread[i]->numInst;
298 /** Add Thread to Active Threads List. */
299 void activateContext(int tid, int delay);
301 /** Remove Thread from Active Threads List */
302 void suspendContext(int tid);
304 /** Remove Thread from Active Threads List &&
305 * Possibly Remove Thread Context from CPU.
307 bool deallocateContext(int tid, bool remove, int delay = 1);
309 /** Remove Thread from Active Threads List &&
310 * Remove Thread Context from CPU.
312 void haltContext(int tid);
314 /** Activate a Thread When CPU Resources are Available. */
315 void activateWhenReady(int tid);
317 /** Add or Remove a Thread Context in the CPU. */
318 void doContextSwitch();
320 /** Update The Order In Which We Process Threads. */
321 void updateThreadPriority();
323 /** Serialize state. */
324 virtual void serialize(std::ostream &os);
326 /** Unserialize from a checkpoint. */
327 virtual void unserialize(Checkpoint *cp, const std::string §ion);
330 /** Executes a syscall on this cycle.
331 * ---------------------------------------
332 * Note: this is a virtual function. CPU-Specific
333 * functionality defined in derived classes
335 virtual void syscall(int tid) { panic("Unimplemented!"); }
337 /** Starts draining the CPU's pipeline of all instructions in
338 * order to stop all memory accesses. */
339 virtual unsigned int drain(Event *drain_event);
341 /** Resumes execution after a drain. */
342 virtual void resume();
344 /** Signals to this CPU that a stage has completed switching out. */
345 void signalDrained();
347 /** Switches out this CPU. */
348 virtual void switchOut();
350 /** Takes over from another CPU. */
351 virtual void takeOverFrom(BaseCPU *oldCPU);
353 /** Get the current instruction sequence number, and increment it. */
354 InstSeqNum getAndIncrementInstSeq()
355 { return globalSeqNum++; }
358 /** Check if this address is a valid instruction address. */
359 bool validInstAddr(Addr addr) { return true; }
361 /** Check if this address is a valid data address. */
362 bool validDataAddr(Addr addr) { return true; }
364 /** Get instruction asid. */
365 int getInstAsid(unsigned tid)
366 { return regFile.miscRegs[tid].getInstAsid(); }
368 /** Get data asid. */
369 int getDataAsid(unsigned tid)
370 { return regFile.miscRegs[tid].getDataAsid(); }
372 /** Get instruction asid. */
373 int getInstAsid(unsigned tid)
374 { return thread[tid]->getInstAsid(); }
376 /** Get data asid. */
377 int getDataAsid(unsigned tid)
378 { return thread[tid]->getDataAsid(); }
382 /** Register accessors. Index refers to the physical register index. */
383 uint64_t readIntReg(int reg_idx);
385 FloatReg readFloatReg(int reg_idx);
387 FloatReg readFloatReg(int reg_idx, int width);
389 FloatRegBits readFloatRegBits(int reg_idx);
391 FloatRegBits readFloatRegBits(int reg_idx, int width);
393 void setIntReg(int reg_idx, uint64_t val);
395 void setFloatReg(int reg_idx, FloatReg val);
397 void setFloatReg(int reg_idx, FloatReg val, int width);
399 void setFloatRegBits(int reg_idx, FloatRegBits val);
401 void setFloatRegBits(int reg_idx, FloatRegBits val, int width);
403 uint64_t readArchIntReg(int reg_idx, unsigned tid);
405 float readArchFloatRegSingle(int reg_idx, unsigned tid);
407 double readArchFloatRegDouble(int reg_idx, unsigned tid);
409 uint64_t readArchFloatRegInt(int reg_idx, unsigned tid);
411 /** Architectural register accessors. Looks up in the commit
412 * rename table to obtain the true physical index of the
413 * architected register first, then accesses that physical
416 void setArchIntReg(int reg_idx, uint64_t val, unsigned tid);
418 void setArchFloatRegSingle(int reg_idx, float val, unsigned tid);
420 void setArchFloatRegDouble(int reg_idx, double val, unsigned tid);
422 void setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid);
424 /** Reads the commit PC of a specific thread. */
425 uint64_t readPC(unsigned tid);
427 /** Sets the commit PC of a specific thread. */
428 void setPC(Addr new_PC, unsigned tid);
430 /** Reads the next PC of a specific thread. */
431 uint64_t readNextPC(unsigned tid);
433 /** Sets the next PC of a specific thread. */
434 void setNextPC(uint64_t val, unsigned tid);
436 /** Reads the next NPC of a specific thread. */
437 uint64_t readNextNPC(unsigned tid);
439 /** Sets the next NPC of a specific thread. */
440 void setNextNPC(uint64_t val, unsigned tid);
442 /** Function to add instruction onto the head of the list of the
443 * instructions. Used when new instructions are fetched.
445 ListIt addInst(DynInstPtr &inst);
447 /** Function to tell the CPU that an instruction has completed. */
448 void instDone(unsigned tid);
450 /** Add Instructions to the CPU Remove List*/
451 void addToRemoveList(DynInstPtr &inst);
453 /** Remove an instruction from the front end of the list. There's
454 * no restriction on location of the instruction.
456 void removeFrontInst(DynInstPtr &inst);
458 /** Remove all instructions that are not currently in the ROB.
459 * There's also an option to not squash delay slot instructions.*/
460 void removeInstsNotInROB(unsigned tid, bool squash_delay_slot,
461 const InstSeqNum &delay_slot_seq_num);
463 /** Remove all instructions younger than the given sequence number. */
464 void removeInstsUntil(const InstSeqNum &seq_num,unsigned tid);
466 /** Removes the instruction pointed to by the iterator. */
467 inline void squashInstIt(const ListIt &instIt, const unsigned &tid);
469 /** Cleans up all instructions on the remove list. */
470 void cleanUpRemovedInsts();
472 /** Debug function to print all instructions on the list. */
476 /** List of all the instructions in flight. */
477 std::list<DynInstPtr> instList;
479 /** List of all the instructions that will be removed at the end of this
482 std::queue<ListIt> removeList;
485 /** Debug structure to keep track of the sequence numbers still in
488 std::set<InstSeqNum> snList;
491 /** Records if instructions need to be removed this cycle due to
492 * being retired or squashed.
494 bool removeInstsThisCycle;
497 /** The fetch stage. */
498 typename CPUPolicy::Fetch fetch;
500 /** The decode stage. */
501 typename CPUPolicy::Decode decode;
503 /** The dispatch stage. */
504 typename CPUPolicy::Rename rename;
506 /** The issue/execute/writeback stages. */
507 typename CPUPolicy::IEW iew;
509 /** The commit stage. */
510 typename CPUPolicy::Commit commit;
512 /** The register file. */
513 typename CPUPolicy::RegFile regFile;
515 /** The free list. */
516 typename CPUPolicy::FreeList freeList;
518 /** The rename map. */
519 typename CPUPolicy::RenameMap renameMap[Impl::MaxThreads];
521 /** The commit rename map. */
522 typename CPUPolicy::RenameMap commitRenameMap[Impl::MaxThreads];
524 /** The re-order buffer. */
525 typename CPUPolicy::ROB rob;
527 /** Active Threads List */
528 std::list<unsigned> activeThreads;
530 /** Integer Register Scoreboard */
531 Scoreboard scoreboard;
534 /** Enum to give each stage a specific index, so when calling
535 * activateStage() or deactivateStage(), they can specify which stage
536 * is being activated/deactivated.
546 /** Typedefs from the Impl to get the structs that each of the
547 * time buffers should use.
549 typedef typename CPUPolicy::TimeStruct TimeStruct;
551 typedef typename CPUPolicy::FetchStruct FetchStruct;
553 typedef typename CPUPolicy::DecodeStruct DecodeStruct;
555 typedef typename CPUPolicy::RenameStruct RenameStruct;
557 typedef typename CPUPolicy::IEWStruct IEWStruct;
559 /** The main time buffer to do backwards communication. */
560 TimeBuffer<TimeStruct> timeBuffer;
562 /** The fetch stage's instruction queue. */
563 TimeBuffer<FetchStruct> fetchQueue;
565 /** The decode stage's instruction queue. */
566 TimeBuffer<DecodeStruct> decodeQueue;
568 /** The rename stage's instruction queue. */
569 TimeBuffer<RenameStruct> renameQueue;
571 /** The IEW stage's instruction queue. */
572 TimeBuffer<IEWStruct> iewQueue;
575 /** The activity recorder; used to tell if the CPU has any
576 * activity remaining or if it can go to idle and deschedule
579 ActivityRecorder activityRec;
582 /** Records that there was time buffer activity this cycle. */
583 void activityThisCycle() { activityRec.activity(); }
585 /** Changes a stage's status to active within the activity recorder. */
586 void activateStage(const StageIdx idx)
587 { activityRec.activateStage(idx); }
589 /** Changes a stage's status to inactive within the activity recorder. */
590 void deactivateStage(const StageIdx idx)
591 { activityRec.deactivateStage(idx); }
593 /** Wakes the CPU, rescheduling the CPU if it's not already active. */
596 /** Gets a free thread id. Use if thread ids change across system. */
600 /** Returns a pointer to a thread context. */
601 ThreadContext *tcBase(unsigned tid)
603 return thread[tid]->getTC();
606 /** The global sequence number counter. */
607 InstSeqNum globalSeqNum;//[Impl::MaxThreads];
609 /** Pointer to the checker, which can dynamically verify
610 * instruction results at run time. This can be set to NULL if it
613 Checker<DynInstPtr> *checker;
616 /** Pointer to the system. */
619 /** Pointer to physical memory. */
620 PhysicalMemory *physmem;
623 /** Event to call process() on once draining has completed. */
626 /** Counter of how many stages have completed draining. */
629 /** Pointers to all of the threads in the CPU. */
630 std::vector<Thread *> thread;
632 /** Whether or not the CPU should defer its registration. */
633 bool deferRegistration;
635 /** Is there a context switch pending? */
638 /** Threads Scheduled to Enter CPU */
639 std::list<int> cpuWaitList;
641 /** The cycle that the CPU was last running, used for statistics. */
642 Tick lastRunningCycle;
644 /** The cycle that the CPU was last activated by a new thread*/
645 Tick lastActivatedCycle;
647 /** Number of Threads CPU can process */
650 /** Mapping for system thread id to cpu id */
651 std::map<unsigned,unsigned> threadMap;
653 /** Available thread ids in the cpu*/
654 std::vector<unsigned> tids;
656 /** Stat for total number of times the CPU is descheduled. */
657 Stats::Scalar<> timesIdled;
658 /** Stat for total number of cycles the CPU spends descheduled. */
659 Stats::Scalar<> idleCycles;
660 /** Stat for the number of committed instructions per thread. */
661 Stats::Vector<> committedInsts;
662 /** Stat for the total number of committed instructions. */
663 Stats::Scalar<> totalCommittedInsts;
664 /** Stat for the CPI per thread. */
666 /** Stat for the total CPI. */
667 Stats::Formula totalCpi;
668 /** Stat for the IPC per thread. */
670 /** Stat for the total IPC. */
671 Stats::Formula totalIpc;
674 #endif // __CPU_O3_CPU_HH__