cpu.hh revision 1684
1//Todo: Add in a lot of the functions that are ISA specific.  Also define
2//the functions that currently exist within the base cpu class.  Define
3//everything for the simobject stuff so it can be serialized and
4//instantiated, add in debugging statements everywhere.  Have CPU schedule
5//itself properly.  Constructor.  Derived alpha class.  Threads!
6// Avoid running stages and advancing queues if idle/stalled.
7
8#ifndef __CPU_BETA_CPU_FULL_CPU_HH__
9#define __CPU_BETA_CPU_FULL_CPU_HH__
10
11#include <iostream>
12#include <list>
13#include <vector>
14
15#include "base/statistics.hh"
16#include "base/timebuf.hh"
17#include "cpu/base_cpu.hh"
18#include "cpu/beta_cpu/comm.hh"
19#include "cpu/beta_cpu/cpu_policy.hh"
20#include "cpu/exec_context.hh"
21#include "sim/process.hh"
22
23#ifdef FULL_SYSTEM
24#include "arch/alpha/ev5.hh"
25using namespace EV5;
26#endif
27
28class FunctionalMemory;
29class Process;
30
31class BaseFullCPU : public BaseCPU
32{
33    //Stuff that's pretty ISA independent will go here.
34  public:
35    typedef BaseCPU::Params Params;
36
37#ifdef FULL_SYSTEM
38    BaseFullCPU(Params &params);
39#else
40    BaseFullCPU(Params &params);
41#endif // FULL_SYSTEM
42
43  private:
44    int cpu_id;
45};
46
47template <class Impl>
48class FullBetaCPU : public BaseFullCPU
49{
50  public:
51    //Put typedefs from the Impl here.
52    typedef typename Impl::ISA ISA;
53    typedef typename Impl::CPUPol CPUPolicy;
54    typedef typename Impl::Params Params;
55    typedef typename Impl::DynInstPtr DynInstPtr;
56
57  public:
58    enum Status {
59        Running,
60        Idle,
61        Halted,
62        Blocked // ?
63    };
64
65    Status _status;
66
67  private:
68    class TickEvent : public Event
69    {
70      private:
71        FullBetaCPU<Impl> *cpu;
72
73      public:
74        TickEvent(FullBetaCPU<Impl> *c);
75        void process();
76        const char *description();
77    };
78
79    TickEvent tickEvent;
80
81    /// Schedule tick event, regardless of its current state.
82    void scheduleTickEvent(int delay)
83    {
84        if (tickEvent.squashed())
85            tickEvent.reschedule(curTick + delay);
86        else if (!tickEvent.scheduled())
87            tickEvent.schedule(curTick + delay);
88    }
89
90    /// Unschedule tick event, regardless of its current state.
91    void unscheduleTickEvent()
92    {
93        if (tickEvent.scheduled())
94            tickEvent.squash();
95    }
96
97  public:
98    FullBetaCPU(Params &params);
99    ~FullBetaCPU();
100
101    void fullCPURegStats();
102
103    void tick();
104
105    void init();
106
107    void activateContext(int thread_num, int delay);
108    void suspendContext(int thread_num);
109    void deallocateContext(int thread_num);
110    void haltContext(int thread_num);
111
112    void switchOut();
113    void takeOverFrom(BaseCPU *oldCPU);
114
115    /** Get the current instruction sequence number, and increment it. */
116    InstSeqNum getAndIncrementInstSeq();
117
118#ifdef FULL_SYSTEM
119    /** Check if this address is a valid instruction address. */
120    bool validInstAddr(Addr addr) { return true; }
121
122    /** Check if this address is a valid data address. */
123    bool validDataAddr(Addr addr) { return true; }
124
125    /** Get instruction asid. */
126    int getInstAsid()
127    { return ITB_ASN_ASN(regFile.getIpr()[ISA::IPR_ITB_ASN]); }
128
129    /** Get data asid. */
130    int getDataAsid()
131    { return DTB_ASN_ASN(regFile.getIpr()[ISA::IPR_DTB_ASN]); }
132#else
133    bool validInstAddr(Addr addr)
134    { return thread[0]->validInstAddr(addr); }
135
136    bool validDataAddr(Addr addr)
137    { return thread[0]->validDataAddr(addr); }
138
139    int getInstAsid() { return thread[0]->asid; }
140    int getDataAsid() { return thread[0]->asid; }
141
142#endif
143
144    //
145    // New accessors for new decoder.
146    //
147    uint64_t readIntReg(int reg_idx);
148
149    float readFloatRegSingle(int reg_idx);
150
151    double readFloatRegDouble(int reg_idx);
152
153    uint64_t readFloatRegInt(int reg_idx);
154
155    void setIntReg(int reg_idx, uint64_t val);
156
157    void setFloatRegSingle(int reg_idx, float val);
158
159    void setFloatRegDouble(int reg_idx, double val);
160
161    void setFloatRegInt(int reg_idx, uint64_t val);
162
163    uint64_t readPC();
164
165    void setNextPC(uint64_t val);
166
167    void setPC(Addr new_PC);
168
169    /** Function to add instruction onto the head of the list of the
170     *  instructions.  Used when new instructions are fetched.
171     */
172    void addInst(DynInstPtr &inst);
173
174    /** Function to tell the CPU that an instruction has completed. */
175    void instDone();
176
177    /** Remove all instructions in back of the given instruction, but leave
178     *  that instruction in the list.  This is useful in a squash, when there
179     *  are instructions in this list that don't exist in structures such as
180     *  the ROB.  The instruction doesn't have to be the last instruction in
181     *  the list, but will be once this function completes.
182     *  @todo: Remove only up until that inst?  Squashed inst is most likely
183     *  valid.
184     */
185    void removeBackInst(DynInstPtr &inst);
186
187    /** Remove an instruction from the front of the list.  It is expected
188     *  that there are no instructions in front of it (that is, none are older
189     *  than the instruction being removed).  Used when retiring instructions.
190     *  @todo: Remove the argument to this function, and just have it remove
191     *  last instruction once it's verified that commit has the same ordering
192     *  as the instruction list.
193     */
194    void removeFrontInst(DynInstPtr &inst);
195
196    /** Remove all instructions that are not currently in the ROB. */
197    void removeInstsNotInROB();
198
199    /** Remove all instructions younger than the given sequence number. */
200    void removeInstsUntil(const InstSeqNum &seq_num);
201
202    /** Remove all instructions from the list. */
203    void removeAllInsts();
204
205    void dumpInsts();
206
207    /** Basically a wrapper function so that instructions executed at
208     *  commit can tell the instruction queue that they have completed.
209     *  Eventually this hack should be removed.
210     */
211    void wakeDependents(DynInstPtr &inst);
212
213  public:
214    /** List of all the instructions in flight. */
215    list<DynInstPtr> instList;
216
217    //not sure these should be private.
218  protected:
219    /** The fetch stage. */
220    typename CPUPolicy::Fetch fetch;
221
222    /** The fetch stage's status. */
223    typename CPUPolicy::Fetch::Status fetchStatus;
224
225    /** The decode stage. */
226    typename CPUPolicy::Decode decode;
227
228    /** The decode stage's status. */
229    typename CPUPolicy::Decode::Status decodeStatus;
230
231    /** The dispatch stage. */
232    typename CPUPolicy::Rename rename;
233
234    /** The dispatch stage's status. */
235    typename CPUPolicy::Rename::Status renameStatus;
236
237    /** The issue/execute/writeback stages. */
238    typename CPUPolicy::IEW iew;
239
240    /** The issue/execute/writeback stage's status. */
241    typename CPUPolicy::IEW::Status iewStatus;
242
243    /** The commit stage. */
244    typename CPUPolicy::Commit commit;
245
246    /** The fetch stage's status. */
247    typename CPUPolicy::Commit::Status commitStatus;
248
249    //Might want to just pass these objects in to the constructors of the
250    //appropriate stage.  regFile is in iew, freeList in dispatch, renameMap
251    //in dispatch, and the rob in commit.
252    /** The register file. */
253    typename CPUPolicy::RegFile regFile;
254
255    /** The free list. */
256    typename CPUPolicy::FreeList freeList;
257
258    /** The rename map. */
259    typename CPUPolicy::RenameMap renameMap;
260
261    /** The re-order buffer. */
262    typename CPUPolicy::ROB rob;
263
264  public:
265    /** Typedefs from the Impl to get the structs that each of the
266     *  time buffers should use.
267     */
268    typedef typename CPUPolicy::TimeStruct TimeStruct;
269
270    typedef typename CPUPolicy::FetchStruct FetchStruct;
271
272    typedef typename CPUPolicy::DecodeStruct DecodeStruct;
273
274    typedef typename CPUPolicy::RenameStruct RenameStruct;
275
276    typedef typename CPUPolicy::IEWStruct IEWStruct;
277
278    /** The main time buffer to do backwards communication. */
279    TimeBuffer<TimeStruct> timeBuffer;
280
281    /** The fetch stage's instruction queue. */
282    TimeBuffer<FetchStruct> fetchQueue;
283
284    /** The decode stage's instruction queue. */
285    TimeBuffer<DecodeStruct> decodeQueue;
286
287    /** The rename stage's instruction queue. */
288    TimeBuffer<RenameStruct> renameQueue;
289
290    /** The IEW stage's instruction queue. */
291    TimeBuffer<IEWStruct> iewQueue;
292
293  public:
294    /** The temporary exec context to support older accessors. */
295    ExecContext *xc;
296
297    /** Temporary function to get pointer to exec context. */
298    ExecContext *xcBase()
299    {
300#ifdef FULL_SYSTEM
301        return system->execContexts[0];
302#else
303        return thread[0];
304#endif
305    }
306
307    InstSeqNum globalSeqNum;
308
309#ifdef FULL_SYSTEM
310    System *system;
311
312    MemoryController *memCtrl;
313    PhysicalMemory *physmem;
314
315    AlphaITB *itb;
316    AlphaDTB *dtb;
317
318//    SWContext *swCtx;
319#else
320    std::vector<ExecContext *> thread;
321#endif
322
323    FunctionalMemory *mem;
324
325    MemInterface *icacheInterface;
326    MemInterface *dcacheInterface;
327
328    bool deferRegistration;
329
330    Counter numInsts;
331
332    Counter funcExeInst;
333};
334
335#endif
336