cpu.hh revision 2190
110396Sakash.bagdia@arm.com/*
210396Sakash.bagdia@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
310396Sakash.bagdia@arm.com * All rights reserved.
410396Sakash.bagdia@arm.com *
510396Sakash.bagdia@arm.com * Redistribution and use in source and binary forms, with or without
610396Sakash.bagdia@arm.com * modification, are permitted provided that the following conditions are
710396Sakash.bagdia@arm.com * met: redistributions of source code must retain the above copyright
810396Sakash.bagdia@arm.com * notice, this list of conditions and the following disclaimer;
910396Sakash.bagdia@arm.com * redistributions in binary form must reproduce the above copyright
1010396Sakash.bagdia@arm.com * notice, this list of conditions and the following disclaimer in the
1110396Sakash.bagdia@arm.com * documentation and/or other materials provided with the distribution;
1210396Sakash.bagdia@arm.com * neither the name of the copyright holders nor the names of its
1310396Sakash.bagdia@arm.com * contributors may be used to endorse or promote products derived from
1410396Sakash.bagdia@arm.com * this software without specific prior written permission.
1510396Sakash.bagdia@arm.com *
1610396Sakash.bagdia@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710396Sakash.bagdia@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810396Sakash.bagdia@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910396Sakash.bagdia@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010396Sakash.bagdia@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110396Sakash.bagdia@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210396Sakash.bagdia@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310396Sakash.bagdia@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410396Sakash.bagdia@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510396Sakash.bagdia@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610396Sakash.bagdia@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710396Sakash.bagdia@arm.com */
2810396Sakash.bagdia@arm.com
2910396Sakash.bagdia@arm.com//Todo: Add in a lot of the functions that are ISA specific.  Also define
3010396Sakash.bagdia@arm.com//the functions that currently exist within the base cpu class.  Define
3110396Sakash.bagdia@arm.com//everything for the simobject stuff so it can be serialized and
3210396Sakash.bagdia@arm.com//instantiated, add in debugging statements everywhere.  Have CPU schedule
3310396Sakash.bagdia@arm.com//itself properly.  Threads!
3410396Sakash.bagdia@arm.com// Avoid running stages and advancing queues if idle/stalled.
3510396Sakash.bagdia@arm.com
3610396Sakash.bagdia@arm.com#ifndef __CPU_O3_CPU_FULL_CPU_HH__
3710396Sakash.bagdia@arm.com#define __CPU_O3_CPU_FULL_CPU_HH__
3810396Sakash.bagdia@arm.com
3910396Sakash.bagdia@arm.com#include <iostream>
4010396Sakash.bagdia@arm.com#include <list>
4110396Sakash.bagdia@arm.com#include <vector>
4210396Sakash.bagdia@arm.com
4310396Sakash.bagdia@arm.com#include "base/statistics.hh"
4410396Sakash.bagdia@arm.com#include "base/timebuf.hh"
4510396Sakash.bagdia@arm.com#include "config/full_system.hh"
4610396Sakash.bagdia@arm.com#include "cpu/base.hh"
4710396Sakash.bagdia@arm.com#include "cpu/cpu_exec_context.hh"
4810396Sakash.bagdia@arm.com#include "cpu/o3/comm.hh"
4910396Sakash.bagdia@arm.com#include "cpu/o3/cpu_policy.hh"
5010396Sakash.bagdia@arm.com#include "sim/process.hh"
5110396Sakash.bagdia@arm.com
5210396Sakash.bagdia@arm.com#if FULL_SYSTEM
5310396Sakash.bagdia@arm.com#include "arch/alpha/ev5.hh"
5410396Sakash.bagdia@arm.comusing namespace EV5;
5510396Sakash.bagdia@arm.com#endif
5610396Sakash.bagdia@arm.com
5710396Sakash.bagdia@arm.comclass ExecContext;
5810396Sakash.bagdia@arm.comclass FunctionalMemory;
5910396Sakash.bagdia@arm.comclass Process;
6010396Sakash.bagdia@arm.com
6110396Sakash.bagdia@arm.comclass BaseFullCPU : public BaseCPU
6210396Sakash.bagdia@arm.com{
6310396Sakash.bagdia@arm.com    //Stuff that's pretty ISA independent will go here.
6410396Sakash.bagdia@arm.com  public:
6510396Sakash.bagdia@arm.com    typedef BaseCPU::Params Params;
6610396Sakash.bagdia@arm.com
6710396Sakash.bagdia@arm.com#if FULL_SYSTEM
6810396Sakash.bagdia@arm.com    BaseFullCPU(Params &params);
6910396Sakash.bagdia@arm.com#else
7010396Sakash.bagdia@arm.com    BaseFullCPU(Params &params);
7110396Sakash.bagdia@arm.com#endif // FULL_SYSTEM
7210396Sakash.bagdia@arm.com
7310396Sakash.bagdia@arm.com  protected:
7410396Sakash.bagdia@arm.com    int cpu_id;
7510396Sakash.bagdia@arm.com};
7610396Sakash.bagdia@arm.com
7710396Sakash.bagdia@arm.comtemplate <class Impl>
7810396Sakash.bagdia@arm.comclass FullO3CPU : public BaseFullCPU
7910396Sakash.bagdia@arm.com{
8010396Sakash.bagdia@arm.com  public:
8110396Sakash.bagdia@arm.com    //Put typedefs from the Impl here.
8210396Sakash.bagdia@arm.com    typedef typename Impl::CPUPol CPUPolicy;
8310396Sakash.bagdia@arm.com    typedef typename Impl::Params Params;
8410396Sakash.bagdia@arm.com    typedef typename Impl::DynInstPtr DynInstPtr;
8510396Sakash.bagdia@arm.com
8610396Sakash.bagdia@arm.com  public:
8710396Sakash.bagdia@arm.com    enum Status {
8810396Sakash.bagdia@arm.com        Running,
8910396Sakash.bagdia@arm.com        Idle,
9010396Sakash.bagdia@arm.com        Halted,
9110396Sakash.bagdia@arm.com        Blocked // ?
9210396Sakash.bagdia@arm.com    };
9310396Sakash.bagdia@arm.com
9410396Sakash.bagdia@arm.com    Status _status;
9510396Sakash.bagdia@arm.com
9610396Sakash.bagdia@arm.com  private:
9710396Sakash.bagdia@arm.com    class TickEvent : public Event
9810396Sakash.bagdia@arm.com    {
9910396Sakash.bagdia@arm.com      private:
10010396Sakash.bagdia@arm.com        FullO3CPU<Impl> *cpu;
10110396Sakash.bagdia@arm.com
10210396Sakash.bagdia@arm.com      public:
10310396Sakash.bagdia@arm.com        TickEvent(FullO3CPU<Impl> *c);
10410396Sakash.bagdia@arm.com        void process();
10510396Sakash.bagdia@arm.com        const char *description();
10610396Sakash.bagdia@arm.com    };
10710396Sakash.bagdia@arm.com
10810396Sakash.bagdia@arm.com    TickEvent tickEvent;
10910396Sakash.bagdia@arm.com
11010396Sakash.bagdia@arm.com    /// Schedule tick event, regardless of its current state.
11110396Sakash.bagdia@arm.com    void scheduleTickEvent(int delay)
11210396Sakash.bagdia@arm.com    {
11310396Sakash.bagdia@arm.com        if (tickEvent.squashed())
11410396Sakash.bagdia@arm.com            tickEvent.reschedule(curTick + delay);
11510396Sakash.bagdia@arm.com        else if (!tickEvent.scheduled())
11610396Sakash.bagdia@arm.com            tickEvent.schedule(curTick + delay);
11710396Sakash.bagdia@arm.com    }
11810396Sakash.bagdia@arm.com
11910396Sakash.bagdia@arm.com    /// Unschedule tick event, regardless of its current state.
12010396Sakash.bagdia@arm.com    void unscheduleTickEvent()
12110396Sakash.bagdia@arm.com    {
12210396Sakash.bagdia@arm.com        if (tickEvent.scheduled())
12310396Sakash.bagdia@arm.com            tickEvent.squash();
12410396Sakash.bagdia@arm.com    }
12510396Sakash.bagdia@arm.com
12610396Sakash.bagdia@arm.com  public:
12710396Sakash.bagdia@arm.com    FullO3CPU(Params &params);
12810396Sakash.bagdia@arm.com    ~FullO3CPU();
12910396Sakash.bagdia@arm.com
13010396Sakash.bagdia@arm.com    void fullCPURegStats();
13110396Sakash.bagdia@arm.com
13210396Sakash.bagdia@arm.com    void tick();
13310396Sakash.bagdia@arm.com
13410396Sakash.bagdia@arm.com    void init();
13510396Sakash.bagdia@arm.com
13610396Sakash.bagdia@arm.com    void activateContext(int thread_num, int delay);
13710396Sakash.bagdia@arm.com    void suspendContext(int thread_num);
13810396Sakash.bagdia@arm.com    void deallocateContext(int thread_num);
13910396Sakash.bagdia@arm.com    void haltContext(int thread_num);
14010396Sakash.bagdia@arm.com
14110396Sakash.bagdia@arm.com    void switchOut();
14210396Sakash.bagdia@arm.com    void takeOverFrom(BaseCPU *oldCPU);
14310396Sakash.bagdia@arm.com
14410396Sakash.bagdia@arm.com    /** Get the current instruction sequence number, and increment it. */
14510396Sakash.bagdia@arm.com    InstSeqNum getAndIncrementInstSeq();
14610396Sakash.bagdia@arm.com
14710396Sakash.bagdia@arm.com#if FULL_SYSTEM
14810396Sakash.bagdia@arm.com    /** Check if this address is a valid instruction address. */
14910396Sakash.bagdia@arm.com    bool validInstAddr(Addr addr) { return true; }
15010396Sakash.bagdia@arm.com
15110396Sakash.bagdia@arm.com    /** Check if this address is a valid data address. */
15210396Sakash.bagdia@arm.com    bool validDataAddr(Addr addr) { return true; }
15310396Sakash.bagdia@arm.com
15410396Sakash.bagdia@arm.com    /** Get instruction asid. */
15510396Sakash.bagdia@arm.com    int getInstAsid()
15610396Sakash.bagdia@arm.com    { return ITB_ASN_ASN(regFile.miscRegs.readReg(TheISA::IPR_ITB_ASN)); }
15710396Sakash.bagdia@arm.com
15810396Sakash.bagdia@arm.com    /** Get data asid. */
15910396Sakash.bagdia@arm.com    int getDataAsid()
16010396Sakash.bagdia@arm.com    { return DTB_ASN_ASN(regFile.miscRegs.readReg(TheISA::IPR_DTB_ASN)); }
16110396Sakash.bagdia@arm.com#else
16210396Sakash.bagdia@arm.com    bool validInstAddr(Addr addr)
16310396Sakash.bagdia@arm.com    { return thread[0]->validInstAddr(addr); }
16410396Sakash.bagdia@arm.com
16510396Sakash.bagdia@arm.com    bool validDataAddr(Addr addr)
16610396Sakash.bagdia@arm.com    { return thread[0]->validDataAddr(addr); }
16710396Sakash.bagdia@arm.com
16810396Sakash.bagdia@arm.com    int getInstAsid() { return thread[0]->getInstAsid(); }
16910396Sakash.bagdia@arm.com    int getDataAsid() { return thread[0]->getDataAsid(); }
17010396Sakash.bagdia@arm.com
17110396Sakash.bagdia@arm.com#endif
17210396Sakash.bagdia@arm.com
17310396Sakash.bagdia@arm.com    //
17410396Sakash.bagdia@arm.com    // New accessors for new decoder.
17510396Sakash.bagdia@arm.com    //
17610396Sakash.bagdia@arm.com    uint64_t readIntReg(int reg_idx);
17710396Sakash.bagdia@arm.com
17810396Sakash.bagdia@arm.com    float readFloatRegSingle(int reg_idx);
17910396Sakash.bagdia@arm.com
18010396Sakash.bagdia@arm.com    double readFloatRegDouble(int reg_idx);
18110396Sakash.bagdia@arm.com
18210396Sakash.bagdia@arm.com    uint64_t readFloatRegInt(int reg_idx);
18310396Sakash.bagdia@arm.com
18410396Sakash.bagdia@arm.com    void setIntReg(int reg_idx, uint64_t val);
18510396Sakash.bagdia@arm.com
18610396Sakash.bagdia@arm.com    void setFloatRegSingle(int reg_idx, float val);
18710396Sakash.bagdia@arm.com
18810396Sakash.bagdia@arm.com    void setFloatRegDouble(int reg_idx, double val);
18910396Sakash.bagdia@arm.com
19010396Sakash.bagdia@arm.com    void setFloatRegInt(int reg_idx, uint64_t val);
19110396Sakash.bagdia@arm.com
19210396Sakash.bagdia@arm.com    uint64_t readPC();
19310396Sakash.bagdia@arm.com
19410396Sakash.bagdia@arm.com    void setNextPC(uint64_t val);
19510396Sakash.bagdia@arm.com
19610396Sakash.bagdia@arm.com    void setPC(Addr new_PC);
19710396Sakash.bagdia@arm.com
19810396Sakash.bagdia@arm.com    /** Function to add instruction onto the head of the list of the
19910396Sakash.bagdia@arm.com     *  instructions.  Used when new instructions are fetched.
20010396Sakash.bagdia@arm.com     */
20110396Sakash.bagdia@arm.com    void addInst(DynInstPtr &inst);
20210396Sakash.bagdia@arm.com
20310396Sakash.bagdia@arm.com    /** Function to tell the CPU that an instruction has completed. */
20410396Sakash.bagdia@arm.com    void instDone();
20510396Sakash.bagdia@arm.com
20610396Sakash.bagdia@arm.com    /** Remove all instructions in back of the given instruction, but leave
20710396Sakash.bagdia@arm.com     *  that instruction in the list.  This is useful in a squash, when there
20810396Sakash.bagdia@arm.com     *  are instructions in this list that don't exist in structures such as
20910396Sakash.bagdia@arm.com     *  the ROB.  The instruction doesn't have to be the last instruction in
21010396Sakash.bagdia@arm.com     *  the list, but will be once this function completes.
21110396Sakash.bagdia@arm.com     *  @todo: Remove only up until that inst?  Squashed inst is most likely
21210396Sakash.bagdia@arm.com     *  valid.
21310396Sakash.bagdia@arm.com     */
21410396Sakash.bagdia@arm.com    void removeBackInst(DynInstPtr &inst);
21510396Sakash.bagdia@arm.com
21610396Sakash.bagdia@arm.com    /** Remove an instruction from the front of the list.  It is expected
21710396Sakash.bagdia@arm.com     *  that there are no instructions in front of it (that is, none are older
21810396Sakash.bagdia@arm.com     *  than the instruction being removed).  Used when retiring instructions.
21910905Sandreas.sandberg@arm.com     *  @todo: Remove the argument to this function, and just have it remove
22010396Sakash.bagdia@arm.com     *  last instruction once it's verified that commit has the same ordering
22110396Sakash.bagdia@arm.com     *  as the instruction list.
22210396Sakash.bagdia@arm.com     */
22310396Sakash.bagdia@arm.com    void removeFrontInst(DynInstPtr &inst);
22410396Sakash.bagdia@arm.com
22510396Sakash.bagdia@arm.com    /** Remove all instructions that are not currently in the ROB. */
22610396Sakash.bagdia@arm.com    void removeInstsNotInROB();
22710396Sakash.bagdia@arm.com
22810396Sakash.bagdia@arm.com    /** Remove all instructions younger than the given sequence number. */
22910396Sakash.bagdia@arm.com    void removeInstsUntil(const InstSeqNum &seq_num);
23010396Sakash.bagdia@arm.com
23110905Sandreas.sandberg@arm.com    /** Remove all instructions from the list. */
23210396Sakash.bagdia@arm.com    void removeAllInsts();
23310396Sakash.bagdia@arm.com
23410396Sakash.bagdia@arm.com    void dumpInsts();
23510396Sakash.bagdia@arm.com
23610396Sakash.bagdia@arm.com    /** Basically a wrapper function so that instructions executed at
23710396Sakash.bagdia@arm.com     *  commit can tell the instruction queue that they have completed.
23810396Sakash.bagdia@arm.com     *  Eventually this hack should be removed.
23910396Sakash.bagdia@arm.com     */
24010396Sakash.bagdia@arm.com    void wakeDependents(DynInstPtr &inst);
24110396Sakash.bagdia@arm.com
24210396Sakash.bagdia@arm.com  public:
24310396Sakash.bagdia@arm.com    /** List of all the instructions in flight. */
24410396Sakash.bagdia@arm.com    list<DynInstPtr> instList;
24510396Sakash.bagdia@arm.com
24610396Sakash.bagdia@arm.com    //not sure these should be private.
24710396Sakash.bagdia@arm.com  protected:
24810396Sakash.bagdia@arm.com    /** The fetch stage. */
24910396Sakash.bagdia@arm.com    typename CPUPolicy::Fetch fetch;
25010396Sakash.bagdia@arm.com
25110396Sakash.bagdia@arm.com    /** The fetch stage's status. */
25210396Sakash.bagdia@arm.com    typename CPUPolicy::Fetch::Status fetchStatus;
25310396Sakash.bagdia@arm.com
25410396Sakash.bagdia@arm.com    /** The decode stage. */
25510396Sakash.bagdia@arm.com    typename CPUPolicy::Decode decode;
25610396Sakash.bagdia@arm.com
25710396Sakash.bagdia@arm.com    /** The decode stage's status. */
25810396Sakash.bagdia@arm.com    typename CPUPolicy::Decode::Status decodeStatus;
25910396Sakash.bagdia@arm.com
26010396Sakash.bagdia@arm.com    /** The dispatch stage. */
26110396Sakash.bagdia@arm.com    typename CPUPolicy::Rename rename;
26210396Sakash.bagdia@arm.com
26310396Sakash.bagdia@arm.com    /** 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    CPUExecContext *cpuXC;
325
326    /** Temporary function to get pointer to exec context. */
327    ExecContext *xcBase()
328    {
329        return thread[0]->getProxy();
330    }
331
332    CPUExecContext *cpuXCBase()
333    {
334        return thread[0];
335    }
336
337    InstSeqNum globalSeqNum;
338
339#if FULL_SYSTEM
340    System *system;
341
342    MemoryController *memCtrl;
343    PhysicalMemory *physmem;
344
345    AlphaITB *itb;
346    AlphaDTB *dtb;
347
348//    SWContext *swCtx;
349#endif
350    std::vector<CPUExecContext *> thread;
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