cpu.hh revision 2354
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
29#ifndef __CPU_O3_CPU_HH__
30#define __CPU_O3_CPU_HH__
31
32#include <iostream>
33#include <list>
34#include <queue>
35#include <set>
36#include <vector>
37
38#include "base/statistics.hh"
39#include "base/timebuf.hh"
40#include "config/full_system.hh"
41#include "cpu/activity.hh"
42#include "cpu/base.hh"
43#include "cpu/cpu_exec_context.hh"
44#include "cpu/o3/comm.hh"
45#include "cpu/o3/cpu_policy.hh"
46#include "cpu/o3/scoreboard.hh"
47#include "cpu/o3/thread_state.hh"
48#include "sim/process.hh"
49
50template <class>
51class Checker;
52class ExecContext;
53class MemInterface;
54class Process;
55
56class BaseFullCPU : public BaseCPU
57{
58    //Stuff that's pretty ISA independent will go here.
59  public:
60    typedef BaseCPU::Params Params;
61
62    BaseFullCPU(Params *params);
63
64    void regStats();
65
66    /** Sets this CPU's ID. */
67    void setCpuId(int id) { cpu_id = id; }
68
69    /** Reads this CPU's ID. */
70    int readCpuId() { return cpu_id; }
71
72  protected:
73    int cpu_id;
74};
75
76/**
77 * FullO3CPU class, has each of the stages (fetch through commit)
78 * within it, as well as all of the time buffers between stages.  The
79 * tick() function for the CPU is defined here.
80 */
81template <class Impl>
82class FullO3CPU : public BaseFullCPU
83{
84  public:
85    // Typedefs from the Impl here.
86    typedef typename Impl::CPUPol CPUPolicy;
87    typedef typename Impl::Params Params;
88    typedef typename Impl::DynInstPtr DynInstPtr;
89
90    typedef O3ThreadState<Impl> Thread;
91
92    typedef typename std::list<DynInstPtr>::iterator ListIt;
93
94  public:
95    enum Status {
96        Running,
97        Idle,
98        Halted,
99        Blocked,
100        SwitchedOut
101    };
102
103    /** Overall CPU status. */
104    Status _status;
105
106  private:
107    class TickEvent : public Event
108    {
109      private:
110        /** Pointer to the CPU. */
111        FullO3CPU<Impl> *cpu;
112
113      public:
114        /** Constructs a tick event. */
115        TickEvent(FullO3CPU<Impl> *c);
116
117        /** Processes a tick event, calling tick() on the CPU. */
118        void process();
119        /** Returns the description of the tick event. */
120        const char *description();
121    };
122
123    /** The tick event used for scheduling CPU ticks. */
124    TickEvent tickEvent;
125
126    /** Schedule tick event, regardless of its current state. */
127    void scheduleTickEvent(int delay)
128    {
129        if (tickEvent.squashed())
130            tickEvent.reschedule(curTick + cycles(delay));
131        else if (!tickEvent.scheduled())
132            tickEvent.schedule(curTick + cycles(delay));
133    }
134
135    /** Unschedule tick event, regardless of its current state. */
136    void unscheduleTickEvent()
137    {
138        if (tickEvent.scheduled())
139            tickEvent.squash();
140    }
141
142  public:
143    /** Constructs a CPU with the given parameters. */
144    FullO3CPU(Params *params);
145    /** Destructor. */
146    ~FullO3CPU();
147
148    /** Registers statistics. */
149    void fullCPURegStats();
150
151    /** Ticks CPU, calling tick() on each stage, and checking the overall
152     *  activity to see if the CPU should deschedule itself.
153     */
154    void tick();
155
156    /** Initialize the CPU */
157    void init();
158
159    /** Setup CPU to insert a thread's context */
160    void insertThread(unsigned tid);
161
162    /** Remove all of a thread's context from CPU */
163    void removeThread(unsigned tid);
164
165    /** Count the Total Instructions Committed in the CPU. */
166    virtual Counter totalInstructions() const
167    {
168        Counter total(0);
169
170        for (int i=0; i < thread.size(); i++)
171            total += thread[i]->numInst;
172
173        return total;
174    }
175
176    /** Add Thread to Active Threads List. */
177    void activateContext(int tid, int delay);
178
179    /** Remove Thread from Active Threads List */
180    void suspendContext(int tid);
181
182    /** Remove Thread from Active Threads List &&
183     *  Remove Thread Context from CPU.
184     */
185    void deallocateContext(int tid);
186
187    /** Remove Thread from Active Threads List &&
188     *  Remove Thread Context from CPU.
189     */
190    void haltContext(int tid);
191
192    /** Activate a Thread When CPU Resources are Available. */
193    void activateWhenReady(int tid);
194
195    /** Add or Remove a Thread Context in the CPU. */
196    void doContextSwitch();
197
198    /** Update The Order In Which We Process Threads. */
199    void updateThreadPriority();
200
201    /** Executes a syscall on this cycle.
202     *  ---------------------------------------
203     *  Note: this is a virtual function. CPU-Specific
204     *  functionality defined in derived classes
205     */
206    virtual void syscall(int tid) { panic("Unimplemented!"); }
207
208    /** Switches out this CPU. */
209    void switchOut(Sampler *sampler);
210
211    /** Signals to this CPU that a stage has completed switching out. */
212    void signalSwitched();
213
214    /** Takes over from another CPU. */
215    void takeOverFrom(BaseCPU *oldCPU);
216
217    /** Get the current instruction sequence number, and increment it. */
218    InstSeqNum getAndIncrementInstSeq()
219    { return globalSeqNum++; }
220
221#if FULL_SYSTEM
222    /** Check if this address is a valid instruction address. */
223    bool validInstAddr(Addr addr) { return true; }
224
225    /** Check if this address is a valid data address. */
226    bool validDataAddr(Addr addr) { return true; }
227
228    /** Get instruction asid. */
229    int getInstAsid(unsigned tid)
230    { return regFile.miscRegs[tid].getInstAsid(); }
231
232    /** Get data asid. */
233    int getDataAsid(unsigned tid)
234    { return regFile.miscRegs[tid].getDataAsid(); }
235#else
236    /** Check if this address is a valid instruction address. */
237    bool validInstAddr(Addr addr,unsigned tid)
238    { return thread[tid]->validInstAddr(addr); }
239
240    /** Check if this address is a valid data address. */
241    bool validDataAddr(Addr addr,unsigned tid)
242    { return thread[tid]->validDataAddr(addr); }
243
244    /** Get instruction asid. */
245    int getInstAsid(unsigned tid)
246    { return thread[tid]->asid; }
247
248    /** Get data asid. */
249    int getDataAsid(unsigned tid)
250    { return thread[tid]->asid; }
251
252#endif
253
254    /** Register accessors.  Index refers to the physical register index. */
255    uint64_t readIntReg(int reg_idx);
256
257    float readFloatRegSingle(int reg_idx);
258
259    double readFloatRegDouble(int reg_idx);
260
261    uint64_t readFloatRegInt(int reg_idx);
262
263    void setIntReg(int reg_idx, uint64_t val);
264
265    void setFloatRegSingle(int reg_idx, float val);
266
267    void setFloatRegDouble(int reg_idx, double val);
268
269    void setFloatRegInt(int reg_idx, uint64_t val);
270
271    uint64_t readArchIntReg(int reg_idx, unsigned tid);
272
273    float readArchFloatRegSingle(int reg_idx, unsigned tid);
274
275    double readArchFloatRegDouble(int reg_idx, unsigned tid);
276
277    uint64_t readArchFloatRegInt(int reg_idx, unsigned tid);
278
279    /** Architectural register accessors.  Looks up in the commit
280     * rename table to obtain the true physical index of the
281     * architected register first, then accesses that physical
282     * register.
283     */
284    void setArchIntReg(int reg_idx, uint64_t val, unsigned tid);
285
286    void setArchFloatRegSingle(int reg_idx, float val, unsigned tid);
287
288    void setArchFloatRegDouble(int reg_idx, double val, unsigned tid);
289
290    void setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid);
291
292    /** Reads the commit PC of a specific thread. */
293    uint64_t readPC(unsigned tid);
294
295    /** Sets the commit PC of a specific thread. */
296    void setPC(Addr new_PC, unsigned tid);
297
298    /** Reads the next PC of a specific thread. */
299    uint64_t readNextPC(unsigned tid);
300
301    /** Sets the next PC of a specific thread. */
302    void setNextPC(uint64_t val, unsigned tid);
303
304    /** Function to add instruction onto the head of the list of the
305     *  instructions.  Used when new instructions are fetched.
306     */
307    ListIt addInst(DynInstPtr &inst);
308
309    /** Function to tell the CPU that an instruction has completed. */
310    void instDone(unsigned tid);
311
312    /** Add Instructions to the CPU Remove List*/
313    void addToRemoveList(DynInstPtr &inst);
314
315    /** Remove an instruction from the front end of the list.  There's
316     *  no restriction on location of the instruction.
317     */
318    void removeFrontInst(DynInstPtr &inst);
319
320    /** Remove all instructions that are not currently in the ROB. */
321    void removeInstsNotInROB(unsigned tid);
322
323    /** Remove all instructions younger than the given sequence number. */
324    void removeInstsUntil(const InstSeqNum &seq_num,unsigned tid);
325
326    /** Removes the instruction pointed to by the iterator. */
327    inline void squashInstIt(const ListIt &instIt, const unsigned &tid);
328
329    /** Cleans up all instructions on the remove list. */
330    void cleanUpRemovedInsts();
331
332    /** Debug function to print all instructions on the list. */
333    void dumpInsts();
334
335  public:
336    /** List of all the instructions in flight. */
337    std::list<DynInstPtr> instList;
338
339    /** List of all the instructions that will be removed at the end of this
340     *  cycle.
341     */
342    std::queue<ListIt> removeList;
343
344#ifdef DEBUG
345    /** Debug structure to keep track of the sequence numbers still in
346     * flight.
347     */
348    std::set<InstSeqNum> snList;
349#endif
350
351    /** Records if instructions need to be removed this cycle due to
352     *  being retired or squashed.
353     */
354    bool removeInstsThisCycle;
355
356  protected:
357    /** The fetch stage. */
358    typename CPUPolicy::Fetch fetch;
359
360    /** The decode stage. */
361    typename CPUPolicy::Decode decode;
362
363    /** The dispatch stage. */
364    typename CPUPolicy::Rename rename;
365
366    /** The issue/execute/writeback stages. */
367    typename CPUPolicy::IEW iew;
368
369    /** The commit stage. */
370    typename CPUPolicy::Commit commit;
371
372    /** The register file. */
373    typename CPUPolicy::RegFile regFile;
374
375    /** The free list. */
376    typename CPUPolicy::FreeList freeList;
377
378    /** The rename map. */
379    typename CPUPolicy::RenameMap renameMap[Impl::MaxThreads];
380
381    /** The commit rename map. */
382    typename CPUPolicy::RenameMap commitRenameMap[Impl::MaxThreads];
383
384    /** The re-order buffer. */
385    typename CPUPolicy::ROB rob;
386
387    /** Active Threads List */
388    std::list<unsigned> activeThreads;
389
390    /** Integer Register Scoreboard */
391    Scoreboard scoreboard;
392
393  public:
394    /** Enum to give each stage a specific index, so when calling
395     *  activateStage() or deactivateStage(), they can specify which stage
396     *  is being activated/deactivated.
397     */
398    enum StageIdx {
399        FetchIdx,
400        DecodeIdx,
401        RenameIdx,
402        IEWIdx,
403        CommitIdx,
404        NumStages };
405
406    /** Typedefs from the Impl to get the structs that each of the
407     *  time buffers should use.
408     */
409    typedef typename CPUPolicy::TimeStruct TimeStruct;
410
411    typedef typename CPUPolicy::FetchStruct FetchStruct;
412
413    typedef typename CPUPolicy::DecodeStruct DecodeStruct;
414
415    typedef typename CPUPolicy::RenameStruct RenameStruct;
416
417    typedef typename CPUPolicy::IEWStruct IEWStruct;
418
419    /** The main time buffer to do backwards communication. */
420    TimeBuffer<TimeStruct> timeBuffer;
421
422    /** The fetch stage's instruction queue. */
423    TimeBuffer<FetchStruct> fetchQueue;
424
425    /** The decode stage's instruction queue. */
426    TimeBuffer<DecodeStruct> decodeQueue;
427
428    /** The rename stage's instruction queue. */
429    TimeBuffer<RenameStruct> renameQueue;
430
431    /** The IEW stage's instruction queue. */
432    TimeBuffer<IEWStruct> iewQueue;
433
434  private:
435    /** The activity recorder; used to tell if the CPU has any
436     * activity remaining or if it can go to idle and deschedule
437     * itself.
438     */
439    ActivityRecorder activityRec;
440
441  public:
442    /** Records that there was time buffer activity this cycle. */
443    void activityThisCycle() { activityRec.activity(); }
444
445    /** Changes a stage's status to active within the activity recorder. */
446    void activateStage(const StageIdx idx)
447    { activityRec.activateStage(idx); }
448
449    /** Changes a stage's status to inactive within the activity recorder. */
450    void deactivateStage(const StageIdx idx)
451    { activityRec.deactivateStage(idx); }
452
453    /** Wakes the CPU, rescheduling the CPU if it's not already active. */
454    void wakeCPU();
455
456    /** Gets a free thread id. Use if thread ids change across system. */
457    int getFreeTid();
458
459  public:
460    /** Returns a pointer to a thread's exec context. */
461    ExecContext *xcBase(unsigned tid)
462    {
463        return thread[tid]->getXCProxy();
464    }
465
466    /** The global sequence number counter. */
467    InstSeqNum globalSeqNum;
468
469    /** Pointer to the checker, which can dynamically verify
470     * instruction results at run time.  This can be set to NULL if it
471     * is not being used.
472     */
473    Checker<DynInstPtr> *checker;
474
475#if FULL_SYSTEM
476    /** Pointer to the system. */
477    System *system;
478
479    /** Pointer to the memory controller. */
480    MemoryController *memCtrl;
481    /** Pointer to physical memory. */
482    PhysicalMemory *physmem;
483#endif
484
485    /** Pointer to memory. */
486    FunctionalMemory *mem;
487
488    /** Pointer to the sampler */
489    Sampler *sampler;
490
491    /** Counter of how many stages have completed switching out. */
492    int switchCount;
493
494    /** Pointers to all of the threads in the CPU. */
495    std::vector<Thread *> thread;
496
497#if 0
498    /** Page table pointer. */
499    PageTable *pTable;
500#endif
501
502    /** Pointer to the icache interface. */
503    MemInterface *icacheInterface;
504    /** Pointer to the dcache interface. */
505    MemInterface *dcacheInterface;
506
507    /** Whether or not the CPU should defer its registration. */
508    bool deferRegistration;
509
510    /** Is there a context switch pending? */
511    bool contextSwitch;
512
513    /** Threads Scheduled to Enter CPU */
514    std::list<int> cpuWaitList;
515
516    /** The cycle that the CPU was last running, used for statistics. */
517    Tick lastRunningCycle;
518
519    /** Number of Threads CPU can process */
520    unsigned numThreads;
521
522    /** Mapping for system thread id to cpu id */
523    std::map<unsigned,unsigned> threadMap;
524
525    /** Available thread ids in the cpu*/
526    std::vector<unsigned> tids;
527
528    /** Stat for total number of times the CPU is descheduled. */
529    Stats::Scalar<> timesIdled;
530    /** Stat for total number of cycles the CPU spends descheduled. */
531    Stats::Scalar<> idleCycles;
532    /** Stat for the number of committed instructions per thread. */
533    Stats::Vector<> committedInsts;
534    /** Stat for the total number of committed instructions. */
535    Stats::Scalar<> totalCommittedInsts;
536    /** Stat for the CPI per thread. */
537    Stats::Formula cpi;
538    /** Stat for the total CPI. */
539    Stats::Formula totalCpi;
540    /** Stat for the IPC per thread. */
541    Stats::Formula ipc;
542    /** Stat for the total IPC. */
543    Stats::Formula totalIpc;
544};
545
546#endif // __CPU_O3_CPU_HH__
547