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