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