cpu.hh revision 5529
1/*
2 * Copyright (c) 2004-2005 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;
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.
15 *
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.
27 *
28 * Authors: Kevin Lim
29 *          Korey Sewell
30 */
31
32#ifndef __CPU_O3_CPU_HH__
33#define __CPU_O3_CPU_HH__
34
35#include <iostream>
36#include <list>
37#include <queue>
38#include <set>
39#include <vector>
40
41#include "arch/types.hh"
42#include "base/statistics.hh"
43#include "base/timebuf.hh"
44#include "config/full_system.hh"
45#include "config/use_checker.hh"
46#include "cpu/activity.hh"
47#include "cpu/base.hh"
48#include "cpu/simple_thread.hh"
49#include "cpu/o3/comm.hh"
50#include "cpu/o3/cpu_policy.hh"
51#include "cpu/o3/scoreboard.hh"
52#include "cpu/o3/thread_state.hh"
53//#include "cpu/o3/thread_context.hh"
54#include "sim/process.hh"
55
56#include "params/DerivO3CPU.hh"
57
58template <class>
59class Checker;
60class ThreadContext;
61template <class>
62class O3ThreadContext;
63
64class Checkpoint;
65class MemObject;
66class Process;
67
68class BaseCPUParams;
69
70class BaseO3CPU : public BaseCPU
71{
72    //Stuff that's pretty ISA independent will go here.
73  public:
74    BaseO3CPU(BaseCPUParams *params);
75
76    void regStats();
77
78    /** Sets this CPU's ID. */
79    void setCpuId(int id) { cpu_id = id; }
80
81    /** Reads this CPU's ID. */
82    int readCpuId() { return cpu_id; }
83
84  protected:
85    int cpu_id;
86};
87
88/**
89 * FullO3CPU class, has each of the stages (fetch through commit)
90 * within it, as well as all of the time buffers between stages.  The
91 * tick() function for the CPU is defined here.
92 */
93template <class Impl>
94class FullO3CPU : public BaseO3CPU
95{
96  public:
97    // Typedefs from the Impl here.
98    typedef typename Impl::CPUPol CPUPolicy;
99    typedef typename Impl::DynInstPtr DynInstPtr;
100    typedef typename Impl::O3CPU O3CPU;
101
102    typedef O3ThreadState<Impl> Thread;
103
104    typedef typename std::list<DynInstPtr>::iterator ListIt;
105
106    friend class O3ThreadContext<Impl>;
107
108  public:
109    enum Status {
110        Running,
111        Idle,
112        Halted,
113        Blocked,
114        SwitchedOut
115    };
116
117    TheISA::ITB * itb;
118    TheISA::DTB * dtb;
119
120    /** Overall CPU status. */
121    Status _status;
122
123    /** Per-thread status in CPU, used for SMT.  */
124    Status _threadStatus[Impl::MaxThreads];
125
126  private:
127    class TickEvent : public Event
128    {
129      private:
130        /** Pointer to the CPU. */
131        FullO3CPU<Impl> *cpu;
132
133      public:
134        /** Constructs a tick event. */
135        TickEvent(FullO3CPU<Impl> *c);
136
137        /** Processes a tick event, calling tick() on the CPU. */
138        void process();
139        /** Returns the description of the tick event. */
140        const char *description() const;
141    };
142
143    /** The tick event used for scheduling CPU ticks. */
144    TickEvent tickEvent;
145
146    /** Schedule tick event, regardless of its current state. */
147    void scheduleTickEvent(int delay)
148    {
149        if (tickEvent.squashed())
150            tickEvent.reschedule(nextCycle(curTick + ticks(delay)));
151        else if (!tickEvent.scheduled())
152            tickEvent.schedule(nextCycle(curTick + ticks(delay)));
153    }
154
155    /** Unschedule tick event, regardless of its current state. */
156    void unscheduleTickEvent()
157    {
158        if (tickEvent.scheduled())
159            tickEvent.squash();
160    }
161
162    class ActivateThreadEvent : public Event
163    {
164      private:
165        /** Number of Thread to Activate */
166        int tid;
167
168        /** Pointer to the CPU. */
169        FullO3CPU<Impl> *cpu;
170
171      public:
172        /** Constructs the event. */
173        ActivateThreadEvent();
174
175        /** Initialize Event */
176        void init(int thread_num, FullO3CPU<Impl> *thread_cpu);
177
178        /** Processes the event, calling activateThread() on the CPU. */
179        void process();
180
181        /** Returns the description of the event. */
182        const char *description() const;
183    };
184
185    /** Schedule thread to activate , regardless of its current state. */
186    void scheduleActivateThreadEvent(int tid, int delay)
187    {
188        // Schedule thread to activate, regardless of its current state.
189        if (activateThreadEvent[tid].squashed())
190            activateThreadEvent[tid].
191                reschedule(nextCycle(curTick + ticks(delay)));
192        else if (!activateThreadEvent[tid].scheduled())
193            activateThreadEvent[tid].
194                schedule(nextCycle(curTick + ticks(delay)));
195    }
196
197    /** Unschedule actiavte thread event, regardless of its current state. */
198    void unscheduleActivateThreadEvent(int tid)
199    {
200        if (activateThreadEvent[tid].scheduled())
201            activateThreadEvent[tid].squash();
202    }
203
204    /** The tick event used for scheduling CPU ticks. */
205    ActivateThreadEvent activateThreadEvent[Impl::MaxThreads];
206
207    class DeallocateContextEvent : public Event
208    {
209      private:
210        /** Number of Thread to deactivate */
211        int tid;
212
213        /** Should the thread be removed from the CPU? */
214        bool remove;
215
216        /** Pointer to the CPU. */
217        FullO3CPU<Impl> *cpu;
218
219      public:
220        /** Constructs the event. */
221        DeallocateContextEvent();
222
223        /** Initialize Event */
224        void init(int thread_num, FullO3CPU<Impl> *thread_cpu);
225
226        /** Processes the event, calling activateThread() on the CPU. */
227        void process();
228
229        /** Sets whether the thread should also be removed from the CPU. */
230        void setRemove(bool _remove) { remove = _remove; }
231
232        /** Returns the description of the event. */
233        const char *description() const;
234    };
235
236    /** Schedule cpu to deallocate thread context.*/
237    void scheduleDeallocateContextEvent(int tid, bool remove, int delay)
238    {
239        // Schedule thread to activate, regardless of its current state.
240        if (deallocateContextEvent[tid].squashed())
241            deallocateContextEvent[tid].
242                reschedule(nextCycle(curTick + ticks(delay)));
243        else if (!deallocateContextEvent[tid].scheduled())
244            deallocateContextEvent[tid].
245                schedule(nextCycle(curTick + ticks(delay)));
246    }
247
248    /** Unschedule thread deallocation in CPU */
249    void unscheduleDeallocateContextEvent(int tid)
250    {
251        if (deallocateContextEvent[tid].scheduled())
252            deallocateContextEvent[tid].squash();
253    }
254
255    /** The tick event used for scheduling CPU ticks. */
256    DeallocateContextEvent deallocateContextEvent[Impl::MaxThreads];
257
258  public:
259    /** Constructs a CPU with the given parameters. */
260    FullO3CPU(O3CPU *o3_cpu, DerivO3CPUParams *params);
261    /** Destructor. */
262    ~FullO3CPU();
263
264    /** Registers statistics. */
265    void fullCPURegStats();
266
267    void demapPage(Addr vaddr, uint64_t asn)
268    {
269        this->itb->demapPage(vaddr, asn);
270        this->dtb->demapPage(vaddr, asn);
271    }
272
273    void demapInstPage(Addr vaddr, uint64_t asn)
274    {
275        this->itb->demapPage(vaddr, asn);
276    }
277
278    void demapDataPage(Addr vaddr, uint64_t asn)
279    {
280        this->dtb->demapPage(vaddr, asn);
281    }
282
283    /** Translates instruction requestion. */
284    Fault translateInstReq(RequestPtr &req, Thread *thread)
285    {
286        return this->itb->translate(req, thread->getTC());
287    }
288
289    /** Translates data read request. */
290    Fault translateDataReadReq(RequestPtr &req, Thread *thread)
291    {
292        return this->dtb->translate(req, thread->getTC(), false);
293    }
294
295    /** Translates data write request. */
296    Fault translateDataWriteReq(RequestPtr &req, Thread *thread)
297    {
298        return this->dtb->translate(req, thread->getTC(), true);
299    }
300
301    /** Returns a specific port. */
302    Port *getPort(const std::string &if_name, int idx);
303
304    /** Ticks CPU, calling tick() on each stage, and checking the overall
305     *  activity to see if the CPU should deschedule itself.
306     */
307    void tick();
308
309    /** Initialize the CPU */
310    void init();
311
312    /** Returns the Number of Active Threads in the CPU */
313    int numActiveThreads()
314    { return activeThreads.size(); }
315
316    /** Add Thread to Active Threads List */
317    void activateThread(unsigned tid);
318
319    /** Remove Thread from Active Threads List */
320    void deactivateThread(unsigned tid);
321
322    /** Setup CPU to insert a thread's context */
323    void insertThread(unsigned tid);
324
325    /** Remove all of a thread's context from CPU */
326    void removeThread(unsigned tid);
327
328    /** Count the Total Instructions Committed in the CPU. */
329    virtual Counter totalInstructions() const
330    {
331        Counter total(0);
332
333        for (int i=0; i < thread.size(); i++)
334            total += thread[i]->numInst;
335
336        return total;
337    }
338
339    /** Add Thread to Active Threads List. */
340    void activateContext(int tid, int delay);
341
342    /** Remove Thread from Active Threads List */
343    void suspendContext(int tid);
344
345    /** Remove Thread from Active Threads List &&
346     *  Possibly Remove Thread Context from CPU.
347     */
348    bool deallocateContext(int tid, bool remove, int delay = 1);
349
350    /** Remove Thread from Active Threads List &&
351     *  Remove Thread Context from CPU.
352     */
353    void haltContext(int tid);
354
355    /** Activate a Thread When CPU Resources are Available. */
356    void activateWhenReady(int tid);
357
358    /** Add or Remove a Thread Context in the CPU. */
359    void doContextSwitch();
360
361    /** Update The Order In Which We Process Threads. */
362    void updateThreadPriority();
363
364    /** Serialize state. */
365    virtual void serialize(std::ostream &os);
366
367    /** Unserialize from a checkpoint. */
368    virtual void unserialize(Checkpoint *cp, const std::string &section);
369
370  public:
371    /** Executes a syscall on this cycle.
372     *  ---------------------------------------
373     *  Note: this is a virtual function. CPU-Specific
374     *  functionality defined in derived classes
375     */
376    virtual void syscall(int tid) { panic("Unimplemented!"); }
377
378    /** Starts draining the CPU's pipeline of all instructions in
379     * order to stop all memory accesses. */
380    virtual unsigned int drain(Event *drain_event);
381
382    /** Resumes execution after a drain. */
383    virtual void resume();
384
385    /** Signals to this CPU that a stage has completed switching out. */
386    void signalDrained();
387
388    /** Switches out this CPU. */
389    virtual void switchOut();
390
391    /** Takes over from another CPU. */
392    virtual void takeOverFrom(BaseCPU *oldCPU);
393
394    /** Get the current instruction sequence number, and increment it. */
395    InstSeqNum getAndIncrementInstSeq()
396    { return globalSeqNum++; }
397
398#if FULL_SYSTEM
399    /** Update the Virt and Phys ports of all ThreadContexts to
400     * reflect change in memory connections. */
401    void updateMemPorts();
402
403    /** Check if this address is a valid instruction address. */
404    bool validInstAddr(Addr addr) { return true; }
405
406    /** Check if this address is a valid data address. */
407    bool validDataAddr(Addr addr) { return true; }
408
409    /** Get instruction asid. */
410    int getInstAsid(unsigned tid)
411    { return regFile.miscRegs[tid].getInstAsid(); }
412
413    /** Get data asid. */
414    int getDataAsid(unsigned tid)
415    { return regFile.miscRegs[tid].getDataAsid(); }
416#else
417    /** Get instruction asid. */
418    int getInstAsid(unsigned tid)
419    { return thread[tid]->getInstAsid(); }
420
421    /** Get data asid. */
422    int getDataAsid(unsigned tid)
423    { return thread[tid]->getDataAsid(); }
424
425#endif
426
427    /** Register accessors.  Index refers to the physical register index. */
428    uint64_t readIntReg(int reg_idx);
429
430    TheISA::FloatReg readFloatReg(int reg_idx);
431
432    TheISA::FloatReg readFloatReg(int reg_idx, int width);
433
434    TheISA::FloatRegBits readFloatRegBits(int reg_idx);
435
436    TheISA::FloatRegBits readFloatRegBits(int reg_idx, int width);
437
438    void setIntReg(int reg_idx, uint64_t val);
439
440    void setFloatReg(int reg_idx, TheISA::FloatReg val);
441
442    void setFloatReg(int reg_idx, TheISA::FloatReg val, int width);
443
444    void setFloatRegBits(int reg_idx, TheISA::FloatRegBits val);
445
446    void setFloatRegBits(int reg_idx, TheISA::FloatRegBits val, int width);
447
448    uint64_t readArchIntReg(int reg_idx, unsigned tid);
449
450    float readArchFloatRegSingle(int reg_idx, unsigned tid);
451
452    double readArchFloatRegDouble(int reg_idx, unsigned tid);
453
454    uint64_t readArchFloatRegInt(int reg_idx, unsigned tid);
455
456    /** Architectural register accessors.  Looks up in the commit
457     * rename table to obtain the true physical index of the
458     * architected register first, then accesses that physical
459     * register.
460     */
461    void setArchIntReg(int reg_idx, uint64_t val, unsigned tid);
462
463    void setArchFloatRegSingle(int reg_idx, float val, unsigned tid);
464
465    void setArchFloatRegDouble(int reg_idx, double val, unsigned tid);
466
467    void setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid);
468
469    /** Reads the commit PC of a specific thread. */
470    Addr readPC(unsigned tid);
471
472    /** Sets the commit PC of a specific thread. */
473    void setPC(Addr new_PC, unsigned tid);
474
475    /** Reads the commit micro PC of a specific thread. */
476    Addr readMicroPC(unsigned tid);
477
478    /** Sets the commmit micro PC of a specific thread. */
479    void setMicroPC(Addr new_microPC, unsigned tid);
480
481    /** Reads the next PC of a specific thread. */
482    Addr readNextPC(unsigned tid);
483
484    /** Sets the next PC of a specific thread. */
485    void setNextPC(Addr val, unsigned tid);
486
487    /** Reads the next NPC of a specific thread. */
488    Addr readNextNPC(unsigned tid);
489
490    /** Sets the next NPC of a specific thread. */
491    void setNextNPC(Addr val, unsigned tid);
492
493    /** Reads the commit next micro PC of a specific thread. */
494    Addr readNextMicroPC(unsigned tid);
495
496    /** Sets the commit next micro PC of a specific thread. */
497    void setNextMicroPC(Addr val, unsigned tid);
498
499    /** Function to add instruction onto the head of the list of the
500     *  instructions.  Used when new instructions are fetched.
501     */
502    ListIt addInst(DynInstPtr &inst);
503
504    /** Function to tell the CPU that an instruction has completed. */
505    void instDone(unsigned tid);
506
507    /** Add Instructions to the CPU Remove List*/
508    void addToRemoveList(DynInstPtr &inst);
509
510    /** Remove an instruction from the front end of the list.  There's
511     *  no restriction on location of the instruction.
512     */
513    void removeFrontInst(DynInstPtr &inst);
514
515    /** Remove all instructions that are not currently in the ROB.
516     *  There's also an option to not squash delay slot instructions.*/
517    void removeInstsNotInROB(unsigned tid);
518
519    /** Remove all instructions younger than the given sequence number. */
520    void removeInstsUntil(const InstSeqNum &seq_num,unsigned tid);
521
522    /** Removes the instruction pointed to by the iterator. */
523    inline void squashInstIt(const ListIt &instIt, const unsigned &tid);
524
525    /** Cleans up all instructions on the remove list. */
526    void cleanUpRemovedInsts();
527
528    /** Debug function to print all instructions on the list. */
529    void dumpInsts();
530
531  public:
532    /** List of all the instructions in flight. */
533    std::list<DynInstPtr> instList;
534
535    /** List of all the instructions that will be removed at the end of this
536     *  cycle.
537     */
538    std::queue<ListIt> removeList;
539
540#ifdef DEBUG
541    /** Debug structure to keep track of the sequence numbers still in
542     * flight.
543     */
544    std::set<InstSeqNum> snList;
545#endif
546
547    /** Records if instructions need to be removed this cycle due to
548     *  being retired or squashed.
549     */
550    bool removeInstsThisCycle;
551
552  protected:
553    /** The fetch stage. */
554    typename CPUPolicy::Fetch fetch;
555
556    /** The decode stage. */
557    typename CPUPolicy::Decode decode;
558
559    /** The dispatch stage. */
560    typename CPUPolicy::Rename rename;
561
562    /** The issue/execute/writeback stages. */
563    typename CPUPolicy::IEW iew;
564
565    /** The commit stage. */
566    typename CPUPolicy::Commit commit;
567
568    /** The register file. */
569    typename CPUPolicy::RegFile regFile;
570
571    /** The free list. */
572    typename CPUPolicy::FreeList freeList;
573
574    /** The rename map. */
575    typename CPUPolicy::RenameMap renameMap[Impl::MaxThreads];
576
577    /** The commit rename map. */
578    typename CPUPolicy::RenameMap commitRenameMap[Impl::MaxThreads];
579
580    /** The re-order buffer. */
581    typename CPUPolicy::ROB rob;
582
583    /** Active Threads List */
584    std::list<unsigned> activeThreads;
585
586    /** Integer Register Scoreboard */
587    Scoreboard scoreboard;
588
589  public:
590    /** Enum to give each stage a specific index, so when calling
591     *  activateStage() or deactivateStage(), they can specify which stage
592     *  is being activated/deactivated.
593     */
594    enum StageIdx {
595        FetchIdx,
596        DecodeIdx,
597        RenameIdx,
598        IEWIdx,
599        CommitIdx,
600        NumStages };
601
602    /** Typedefs from the Impl to get the structs that each of the
603     *  time buffers should use.
604     */
605    typedef typename CPUPolicy::TimeStruct TimeStruct;
606
607    typedef typename CPUPolicy::FetchStruct FetchStruct;
608
609    typedef typename CPUPolicy::DecodeStruct DecodeStruct;
610
611    typedef typename CPUPolicy::RenameStruct RenameStruct;
612
613    typedef typename CPUPolicy::IEWStruct IEWStruct;
614
615    /** The main time buffer to do backwards communication. */
616    TimeBuffer<TimeStruct> timeBuffer;
617
618    /** The fetch stage's instruction queue. */
619    TimeBuffer<FetchStruct> fetchQueue;
620
621    /** The decode stage's instruction queue. */
622    TimeBuffer<DecodeStruct> decodeQueue;
623
624    /** The rename stage's instruction queue. */
625    TimeBuffer<RenameStruct> renameQueue;
626
627    /** The IEW stage's instruction queue. */
628    TimeBuffer<IEWStruct> iewQueue;
629
630  private:
631    /** The activity recorder; used to tell if the CPU has any
632     * activity remaining or if it can go to idle and deschedule
633     * itself.
634     */
635    ActivityRecorder activityRec;
636
637  public:
638    /** Records that there was time buffer activity this cycle. */
639    void activityThisCycle() { activityRec.activity(); }
640
641    /** Changes a stage's status to active within the activity recorder. */
642    void activateStage(const StageIdx idx)
643    { activityRec.activateStage(idx); }
644
645    /** Changes a stage's status to inactive within the activity recorder. */
646    void deactivateStage(const StageIdx idx)
647    { activityRec.deactivateStage(idx); }
648
649    /** Wakes the CPU, rescheduling the CPU if it's not already active. */
650    void wakeCPU();
651
652    /** Gets a free thread id. Use if thread ids change across system. */
653    int getFreeTid();
654
655  public:
656    /** Returns a pointer to a thread context. */
657    ThreadContext *tcBase(unsigned tid)
658    {
659        return thread[tid]->getTC();
660    }
661
662    /** The global sequence number counter. */
663    InstSeqNum globalSeqNum;//[Impl::MaxThreads];
664
665#if USE_CHECKER
666    /** Pointer to the checker, which can dynamically verify
667     * instruction results at run time.  This can be set to NULL if it
668     * is not being used.
669     */
670    Checker<DynInstPtr> *checker;
671#endif
672
673#if FULL_SYSTEM
674    /** Pointer to the system. */
675    System *system;
676
677    /** Pointer to physical memory. */
678    PhysicalMemory *physmem;
679#endif
680
681    /** Event to call process() on once draining has completed. */
682    Event *drainEvent;
683
684    /** Counter of how many stages have completed draining. */
685    int drainCount;
686
687    /** Pointers to all of the threads in the CPU. */
688    std::vector<Thread *> thread;
689
690    /** Whether or not the CPU should defer its registration. */
691    bool deferRegistration;
692
693    /** Is there a context switch pending? */
694    bool contextSwitch;
695
696    /** Threads Scheduled to Enter CPU */
697    std::list<int> cpuWaitList;
698
699    /** The cycle that the CPU was last running, used for statistics. */
700    Tick lastRunningCycle;
701
702    /** The cycle that the CPU was last activated by a new thread*/
703    Tick lastActivatedCycle;
704
705    /** Number of Threads CPU can process */
706    unsigned numThreads;
707
708    /** Mapping for system thread id to cpu id */
709    std::map<unsigned,unsigned> threadMap;
710
711    /** Available thread ids in the cpu*/
712    std::vector<unsigned> tids;
713
714    /** Stat for total number of times the CPU is descheduled. */
715    Stats::Scalar<> timesIdled;
716    /** Stat for total number of cycles the CPU spends descheduled. */
717    Stats::Scalar<> idleCycles;
718    /** Stat for the number of committed instructions per thread. */
719    Stats::Vector<> committedInsts;
720    /** Stat for the total number of committed instructions. */
721    Stats::Scalar<> totalCommittedInsts;
722    /** Stat for the CPI per thread. */
723    Stats::Formula cpi;
724    /** Stat for the total CPI. */
725    Stats::Formula totalCpi;
726    /** Stat for the IPC per thread. */
727    Stats::Formula ipc;
728    /** Stat for the total IPC. */
729    Stats::Formula totalIpc;
730};
731
732#endif // __CPU_O3_CPU_HH__
733