base.hh revision 2566
12068SN/A/*
22068SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
32068SN/A * All rights reserved.
42068SN/A *
52068SN/A * Redistribution and use in source and binary forms, with or without
62068SN/A * modification, are permitted provided that the following conditions are
72068SN/A * met: redistributions of source code must retain the above copyright
82068SN/A * notice, this list of conditions and the following disclaimer;
92068SN/A * redistributions in binary form must reproduce the above copyright
102068SN/A * notice, this list of conditions and the following disclaimer in the
112068SN/A * documentation and/or other materials provided with the distribution;
122068SN/A * neither the name of the copyright holders nor the names of its
132068SN/A * contributors may be used to endorse or promote products derived from
142068SN/A * this software without specific prior written permission.
152068SN/A *
162068SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172068SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182068SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192068SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202068SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212068SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222068SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232068SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242068SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252068SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262068SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272068SN/A */
282665Ssaidi@eecs.umich.edu
292665Ssaidi@eecs.umich.edu#ifndef __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
302068SN/A#define __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
312649Ssaidi@eecs.umich.edu
322649Ssaidi@eecs.umich.edu#include "base/statistics.hh"
332649Ssaidi@eecs.umich.edu#include "config/full_system.hh"
342649Ssaidi@eecs.umich.edu#include "cpu/base.hh"
357799Sgblack@eecs.umich.edu#include "cpu/cpu_exec_context.hh"
367799Sgblack@eecs.umich.edu#include "cpu/pc_event.hh"
377799Sgblack@eecs.umich.edu#include "cpu/sampler/sampler.hh"
382649Ssaidi@eecs.umich.edu#include "cpu/static_inst.hh"
392649Ssaidi@eecs.umich.edu#include "mem/packet.hh"
402068SN/A#include "mem/port.hh"
412068SN/A#include "mem/request.hh"
422068SN/A#include "sim/eventq.hh"
432090SN/A
442090SN/A// forward declarations
4510196SCurtis.Dunham@arm.com#if FULL_SYSTEM
462068SN/Aclass Processor;
477799Sgblack@eecs.umich.educlass AlphaITB;
488738Sgblack@eecs.umich.educlass AlphaDTB;
4910474Sandreas.hansson@arm.comclass MemObject;
502068SN/A
512068SN/Aclass RemoteGDB;
522068SN/Aclass GDBListener;
5312110SRekai.GonzalezAlberquilla@arm.com
5412110SRekai.GonzalezAlberquilla@arm.com#else
5512110SRekai.GonzalezAlberquilla@arm.com
562068SN/Aclass Process;
572068SN/A
582068SN/A#endif // FULL_SYSTEM
592068SN/A
602068SN/Aclass ExecContext;
612068SN/Aclass Checkpoint;
622068SN/A
632068SN/Anamespace Trace {
642068SN/A    class InstRecord;
652068SN/A}
662068SN/A
672068SN/A
682068SN/A// Set exactly one of these symbols to 1 to set the memory access
692068SN/A// model.  Probably should make these template parameters, or even
707799Sgblack@eecs.umich.edu// just fork the CPU models.
712068SN/A//
727799Sgblack@eecs.umich.edu#define SIMPLE_CPU_MEM_TIMING    0
737799Sgblack@eecs.umich.edu#define SIMPLE_CPU_MEM_ATOMIC    0
747799Sgblack@eecs.umich.edu#define SIMPLE_CPU_MEM_IMMEDIATE 1
752068SN/A
762068SN/A
772068SN/Aclass SimpleCPU : public BaseCPU
782068SN/A{
792068SN/A  protected:
802068SN/A    typedef TheISA::MachInst MachInst;
812068SN/A    typedef TheISA::MiscReg MiscReg;
822068SN/A    typedef TheISA::FloatReg FloatReg;
837799Sgblack@eecs.umich.edu    typedef TheISA::FloatRegBits FloatRegBits;
842068SN/A    class CpuPort : public Port
857799Sgblack@eecs.umich.edu    {
867799Sgblack@eecs.umich.edu
872068SN/A        SimpleCPU *cpu;
882068SN/A
892068SN/A      public:
902068SN/A
912068SN/A        CpuPort(SimpleCPU *_cpu)
922068SN/A            : cpu(_cpu)
932068SN/A        { }
942068SN/A
952068SN/A      protected:
962068SN/A
972068SN/A        virtual bool recvTiming(Packet &pkt);
982068SN/A
992068SN/A        virtual Tick recvAtomic(Packet &pkt);
1002068SN/A
1012068SN/A        virtual void recvFunctional(Packet &pkt);
1022068SN/A
1032068SN/A        virtual void recvStatusChange(Status status);
1042068SN/A
1052068SN/A        virtual Packet *recvRetry();
1062068SN/A    };
1072068SN/A
1082068SN/A    MemObject *mem;
1092068SN/A    CpuPort icachePort;
1102068SN/A    CpuPort dcachePort;
1112068SN/A
1122068SN/A  public:
1132068SN/A    // main simulation loop (one cycle)
1142068SN/A    void tick();
1152068SN/A    virtual void init();
1162227SN/A
1172068SN/A  private:
1182068SN/A    struct TickEvent : public Event
1192068SN/A    {
1202068SN/A        SimpleCPU *cpu;
1212068SN/A        int width;
1222068SN/A
1232068SN/A        TickEvent(SimpleCPU *c, int w);
1242068SN/A        void process();
1252068SN/A        const char *description();
1262068SN/A    };
1272068SN/A
1282068SN/A    TickEvent tickEvent;
1292068SN/A
1302068SN/A    /// Schedule tick event, regardless of its current state.
1312068SN/A    void scheduleTickEvent(int numCycles)
1322068SN/A    {
1332068SN/A        if (tickEvent.squashed())
1342068SN/A            tickEvent.reschedule(curTick + cycles(numCycles));
1352068SN/A        else if (!tickEvent.scheduled())
1362068SN/A            tickEvent.schedule(curTick + cycles(numCycles));
1372068SN/A    }
1382068SN/A
1392068SN/A    /// Unschedule tick event, regardless of its current state.
1402068SN/A    void unscheduleTickEvent()
1412068SN/A    {
1422068SN/A        if (tickEvent.scheduled())
1432068SN/A            tickEvent.squash();
1442068SN/A    }
1452068SN/A
1462068SN/A  private:
1472068SN/A    Trace::InstRecord *traceData;
1482068SN/A
1492068SN/A  public:
1502068SN/A    //
1512068SN/A    enum Status {
1522068SN/A        Running,
1532068SN/A        Idle,
1542068SN/A        IcacheRetry,
15512106SRekai.GonzalezAlberquilla@arm.com        IcacheWaitResponse,
1562068SN/A        IcacheAccessComplete,
1572068SN/A        DcacheRetry,
1582068SN/A        DcacheWaitResponse,
1592068SN/A        DcacheWaitSwitch,
1602068SN/A        SwitchedOut
1612068SN/A    };
1622068SN/A
1632068SN/A  private:
1642068SN/A    Status _status;
1652068SN/A
1662068SN/A  public:
1672068SN/A    void post_interrupt(int int_num, int index);
1682068SN/A
1692068SN/A    void zero_fill_64(Addr addr) {
1702068SN/A      static int warned = 0;
1712068SN/A      if (!warned) {
1722068SN/A        warn ("WH64 is not implemented");
1732068SN/A        warned = 1;
1742068SN/A      }
1752068SN/A    };
1762068SN/A
1772068SN/A  public:
1782068SN/A    struct Params : public BaseCPU::Params
1792068SN/A    {
1802068SN/A        int width;
1812068SN/A        MemObject *mem;
1822068SN/A#if FULL_SYSTEM
1832068SN/A        AlphaITB *itb;
1842068SN/A        AlphaDTB *dtb;
1852068SN/A#else
1862068SN/A        Process *process;
1872068SN/A#endif
1882068SN/A    };
1892068SN/A    SimpleCPU(Params *params);
1902068SN/A    virtual ~SimpleCPU();
1917799Sgblack@eecs.umich.edu
1927799Sgblack@eecs.umich.edu  public:
1937799Sgblack@eecs.umich.edu    // execution context
1947799Sgblack@eecs.umich.edu    CPUExecContext *cpuXC;
1952068SN/A
1962068SN/A    ExecContext *xcProxy;
1972068SN/A
1982068SN/A    void switchOut(Sampler *s);
1992068SN/A    void takeOverFrom(BaseCPU *oldCPU);
2002068SN/A
2012068SN/A#if FULL_SYSTEM
2022068SN/A    Addr dbg_vtophys(Addr addr);
2032068SN/A
2042068SN/A    bool interval_stats;
2052068SN/A#endif
2062068SN/A
2072068SN/A    // current instruction
2082068SN/A    MachInst inst;
20910196SCurtis.Dunham@arm.com
2102068SN/A    // Static data storage
2112068SN/A    TheISA::IntReg dataReg;
2122068SN/A
2132068SN/A#if SIMPLE_CPU_MEM_TIMING
2142068SN/A    Packet *retry_pkt;
2152068SN/A#elif SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE
2162068SN/A    Request *ifetch_req;
2172068SN/A    Packet  *ifetch_pkt;
2182132SN/A    Request *data_read_req;
2192068SN/A    Packet  *data_read_pkt;
2202068SN/A    Request *data_write_req;
2212068SN/A    Packet  *data_write_pkt;
2222068SN/A#endif
2232068SN/A
2242068SN/A    // Pointer to the sampler that is telling us to switchover.
2252068SN/A    // Used to signal the completion of the pipe drain and schedule
2262068SN/A    // the next switchover
2274394Ssaidi@eecs.umich.edu    Sampler *sampler;
2287783SGiacomo.Gabrielli@arm.com
2292068SN/A    StaticInstPtr curStaticInst;
2304394Ssaidi@eecs.umich.edu
2312068SN/A    Status status() const { return _status; }
2322068SN/A
2332068SN/A    virtual void activateContext(int thread_num, int delay);
2342068SN/A    virtual void suspendContext(int thread_num);
2352068SN/A    virtual void deallocateContext(int thread_num);
2362068SN/A    virtual void haltContext(int thread_num);
2372068SN/A
2382068SN/A    // statistics
2392068SN/A    virtual void regStats();
2402068SN/A    virtual void resetStats();
2412090SN/A
2422068SN/A    // number of simulated instructions
2432068SN/A    Counter numInst;
2442068SN/A    Counter startNumInst;
2452068SN/A    Stats::Scalar<> numInsts;
2462068SN/A
2472068SN/A    virtual Counter totalInstructions() const
2482068SN/A    {
2492068SN/A        return numInst - startNumInst;
2502068SN/A    }
2512068SN/A
2522068SN/A    // number of simulated memory references
25310196SCurtis.Dunham@arm.com    Stats::Scalar<> numMemRefs;
2542068SN/A
2552068SN/A    // number of simulated loads
2562068SN/A    Counter numLoad;
2572068SN/A    Counter startNumLoad;
2582068SN/A
2592068SN/A    // number of idle cycles
2602068SN/A    Stats::Average<> notIdleFraction;
2612068SN/A    Stats::Formula idleFraction;
2622132SN/A
2632068SN/A    // number of cycles stalled for I-cache responses
2642068SN/A    Stats::Scalar<> icacheStallCycles;
2652068SN/A    Counter lastIcacheStall;
2662068SN/A
2672068SN/A    // number of cycles stalled for I-cache retries
2682068SN/A    Stats::Scalar<> icacheRetryCycles;
2692090SN/A    Counter lastIcacheRetry;
2702068SN/A
2712068SN/A    // number of cycles stalled for D-cache responses
2722068SN/A    Stats::Scalar<> dcacheStallCycles;
2732068SN/A    Counter lastDcacheStall;
2742068SN/A
2752068SN/A    // number of cycles stalled for D-cache retries
2762068SN/A    Stats::Scalar<> dcacheRetryCycles;
2772068SN/A    Counter lastDcacheRetry;
2782068SN/A
2792068SN/A    void sendIcacheRequest(Packet *pkt);
2802068SN/A    void sendDcacheRequest(Packet *pkt);
2812068SN/A    void processResponse(Packet &response);
2822068SN/A
2832068SN/A    Packet * processRetry();
2842068SN/A    void recvStatusChange(Port::Status status) {}
2852068SN/A
2862068SN/A    virtual void serialize(std::ostream &os);
2872068SN/A    virtual void unserialize(Checkpoint *cp, const std::string &section);
2882068SN/A
2892068SN/A    template <class T>
2902068SN/A    Fault read(Addr addr, T &data, unsigned flags);
2912068SN/A
2923953Sstever@eecs.umich.edu    template <class T>
2932068SN/A    Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
2942068SN/A
2952068SN/A    // These functions are only used in CPU models that split
2962068SN/A    // effective address computation from the actual memory access.
2972068SN/A    void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
2982068SN/A    Addr getEA() 	{ panic("SimpleCPU::getEA() not implemented\n"); }
2992068SN/A
3002068SN/A    void prefetch(Addr addr, unsigned flags)
3012068SN/A    {
3023953Sstever@eecs.umich.edu        // need to do this...
3032068SN/A    }
3042068SN/A
3052068SN/A    void writeHint(Addr addr, int size, unsigned flags)
3062068SN/A    {
3072068SN/A        // need to do this...
3082068SN/A    }
309
310    Fault copySrcTranslate(Addr src);
311
312    Fault copy(Addr dest);
313
314    // The register accessor methods provide the index of the
315    // instruction's operand (e.g., 0 or 1), not the architectural
316    // register index, to simplify the implementation of register
317    // renaming.  We find the architectural register index by indexing
318    // into the instruction's own operand index table.  Note that a
319    // raw pointer to the StaticInst is provided instead of a
320    // ref-counted StaticInstPtr to redice overhead.  This is fine as
321    // long as these methods don't copy the pointer into any long-term
322    // storage (which is pretty hard to imagine they would have reason
323    // to do).
324
325    uint64_t readIntReg(const StaticInst *si, int idx)
326    {
327        return cpuXC->readIntReg(si->srcRegIdx(idx));
328    }
329
330    FloatReg readFloatReg(const StaticInst *si, int idx, int width)
331    {
332        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
333        return cpuXC->readFloatReg(reg_idx, width);
334    }
335
336    FloatReg readFloatReg(const StaticInst *si, int idx)
337    {
338        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
339        return cpuXC->readFloatReg(reg_idx);
340    }
341
342    FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width)
343    {
344        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
345        return cpuXC->readFloatRegBits(reg_idx, width);
346    }
347
348    FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
349    {
350        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
351        return cpuXC->readFloatRegBits(reg_idx);
352    }
353
354    void setIntReg(const StaticInst *si, int idx, uint64_t val)
355    {
356        cpuXC->setIntReg(si->destRegIdx(idx), val);
357    }
358
359    void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
360    {
361        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
362        cpuXC->setFloatReg(reg_idx, val, width);
363    }
364
365    void setFloatReg(const StaticInst *si, int idx, FloatReg val)
366    {
367        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
368        cpuXC->setFloatReg(reg_idx, val);
369    }
370
371    void setFloatRegBits(const StaticInst *si, int idx,
372            FloatRegBits val, int width)
373    {
374        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
375        cpuXC->setFloatRegBits(reg_idx, val, width);
376    }
377
378    void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val)
379    {
380        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
381        cpuXC->setFloatRegBits(reg_idx, val);
382    }
383
384    uint64_t readPC() { return cpuXC->readPC(); }
385    uint64_t readNextPC() { return cpuXC->readNextPC(); }
386    uint64_t readNextNPC() { return cpuXC->readNextNPC(); }
387
388    void setPC(uint64_t val) { cpuXC->setPC(val); }
389    void setNextPC(uint64_t val) { cpuXC->setNextPC(val); }
390    void setNextNPC(uint64_t val) { cpuXC->setNextNPC(val); }
391
392    MiscReg readMiscReg(int misc_reg)
393    {
394        return cpuXC->readMiscReg(misc_reg);
395    }
396
397    MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
398    {
399        return cpuXC->readMiscRegWithEffect(misc_reg, fault);
400    }
401
402    Fault setMiscReg(int misc_reg, const MiscReg &val)
403    {
404        return cpuXC->setMiscReg(misc_reg, val);
405    }
406
407    Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
408    {
409        return cpuXC->setMiscRegWithEffect(misc_reg, val);
410    }
411
412#if FULL_SYSTEM
413    Fault hwrei() { return cpuXC->hwrei(); }
414    int readIntrFlag() { return cpuXC->readIntrFlag(); }
415    void setIntrFlag(int val) { cpuXC->setIntrFlag(val); }
416    bool inPalMode() { return cpuXC->inPalMode(); }
417    void ev5_trap(Fault fault) { fault->invoke(xcProxy); }
418    bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
419#else
420    void syscall(int64_t callnum) { cpuXC->syscall(callnum); }
421#endif
422
423    bool misspeculating() { return cpuXC->misspeculating(); }
424    ExecContext *xcBase() { return xcProxy; }
425};
426
427#endif // __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
428