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