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