CheckerCPU: Make CheckerCPU runtime selectable instead of compile selectable
[gem5.git] / src / cpu / simple / base.hh
index 787259c966ed4746078a4fd577b9ee0b69e75502..67fbccf98d801838bfdf7baef589b7fb75b7e94f 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2002-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
 
 #include "arch/predecoder.hh"
 #include "base/statistics.hh"
-#include "config/full_system.hh"
+#include "config/the_isa.hh"
 #include "cpu/base.hh"
-#include "cpu/simple_thread.hh"
+#include "cpu/checker/cpu.hh"
+#include "cpu/decode.hh"
 #include "cpu/pc_event.hh"
+#include "cpu/simple_thread.hh"
 #include "cpu/static_inst.hh"
 #include "mem/packet.hh"
 #include "mem/port.hh"
 #include "mem/request.hh"
 #include "sim/eventq.hh"
+#include "sim/full_system.hh"
+#include "sim/system.hh"
 
 // forward declarations
-#if FULL_SYSTEM
-class Processor;
-namespace TheISA
-{
-    class ITB;
-    class DTB;
-}
-class MemObject;
-
-#else
-
+class Checkpoint;
 class Process;
-
-#endif // FULL_SYSTEM
-
-class RemoteGDB;
-class GDBListener;
+class Processor;
+class ThreadContext;
 
 namespace TheISA
 {
+    class DTB;
+    class ITB;
     class Predecoder;
 }
-class ThreadContext;
-class Checkpoint;
 
 namespace Trace {
     class InstRecord;
 }
 
+struct BaseSimpleCPUParams;
+
 
 class BaseSimpleCPU : public BaseCPU
 {
@@ -86,8 +91,17 @@ class BaseSimpleCPU : public BaseCPU
   protected:
     Trace::InstRecord *traceData;
 
+    inline void checkPcEventQueue() {
+        Addr oldpc, pc = thread->instAddr();
+        do {
+            oldpc = pc;
+            system->pcEventQueue.service(tc);
+            pc = thread->instAddr();
+        } while (oldpc != pc);
+    }
+
   public:
-    void post_interrupt(int int_num, int index);
+    void wakeup();
 
     void zero_fill_64(Addr addr) {
       static int warned = 0;
@@ -98,16 +112,7 @@ class BaseSimpleCPU : public BaseCPU
     };
 
   public:
-    struct Params : public BaseCPU::Params
-    {
-#if FULL_SYSTEM
-        TheISA::ITB *itb;
-        TheISA::DTB *dtb;
-#else
-        Process *process;
-#endif
-    };
-    BaseSimpleCPU(Params *params);
+    BaseSimpleCPU(BaseSimpleCPUParams *params);
     virtual ~BaseSimpleCPU();
 
   public:
@@ -119,11 +124,32 @@ class BaseSimpleCPU : public BaseCPU
      */
     ThreadContext *tc;
 
-#if FULL_SYSTEM
+    CheckerCPU *checker;
+
+  protected:
+
+    enum Status {
+        Idle,
+        Running,
+        Faulting,
+        ITBWaitResponse,
+        IcacheRetry,
+        IcacheWaitResponse,
+        IcacheWaitSwitch,
+        DTBWaitResponse,
+        DcacheRetry,
+        DcacheWaitResponse,
+        DcacheWaitSwitch,
+        SwitchedOut
+    };
+
+    Status _status;
+
+  public:
+
     Addr dbg_vtophys(Addr addr);
 
     bool interval_stats;
-#endif
 
     // current instruction
     TheISA::MachInst inst;
@@ -131,20 +157,23 @@ class BaseSimpleCPU : public BaseCPU
     // The predecoder
     TheISA::Predecoder predecoder;
 
-    // Static data storage
-    TheISA::LargestRead dataReg;
-
     StaticInstPtr curStaticInst;
     StaticInstPtr curMacroStaticInst;
 
+    //This is the offset from the current pc that fetch should be performed at
+    Addr fetchOffset;
+    //This flag says to stay at the current pc. This is useful for
+    //instructions which go beyond MachInst boundaries.
+    bool stayAtPC;
+
     void checkForInterrupts();
-    Fault setupFetchRequest(Request *req);
+    void setupFetchRequest(Request *req);
     void preExecute();
     void postExecute();
     void advancePC(Fault fault);
 
-    virtual void deallocateContext(int thread_num);
-    virtual void haltContext(int thread_num);
+    virtual void deallocateContext(ThreadID thread_num);
+    virtual void haltContext(ThreadID thread_num);
 
     // statistics
     virtual void regStats();
@@ -153,38 +182,93 @@ class BaseSimpleCPU : public BaseCPU
     // number of simulated instructions
     Counter numInst;
     Counter startNumInst;
-    Stats::Scalar<> numInsts;
+    Stats::Scalar numInsts;
+    Counter numOp;
+    Counter startNumOp;
+    Stats::Scalar numOps;
 
-    virtual Counter totalInstructions() const
+    void countInst()
+    {
+        if (!curStaticInst->isMicroop() || curStaticInst->isLastMicroop()) {
+            numInst++;
+            numInsts++;
+        }
+        numOp++;
+        numOps++;
+
+        system->totalNumInsts++;
+        thread->funcExeInst++;
+    }
+
+    virtual Counter totalInsts() const
     {
         return numInst - startNumInst;
     }
 
+    virtual Counter totalOps() const
+    {
+        return numOp - startNumOp;
+    }
+
+    //number of integer alu accesses
+    Stats::Scalar numIntAluAccesses;
+
+    //number of float alu accesses
+    Stats::Scalar numFpAluAccesses;
+
+    //number of function calls/returns
+    Stats::Scalar numCallsReturns;
+
+    //conditional control instructions;
+    Stats::Scalar numCondCtrlInsts;
+
+    //number of int instructions
+    Stats::Scalar numIntInsts;
+
+    //number of float instructions
+    Stats::Scalar numFpInsts;
+
+    //number of integer register file accesses
+    Stats::Scalar numIntRegReads;
+    Stats::Scalar numIntRegWrites;
+
+    //number of float register file accesses
+    Stats::Scalar numFpRegReads;
+    Stats::Scalar numFpRegWrites;
+
     // number of simulated memory references
-    Stats::Scalar<> numMemRefs;
+    Stats::Scalar numMemRefs;
+    Stats::Scalar numLoadInsts;
+    Stats::Scalar numStoreInsts;
+
+    // number of idle cycles
+    Stats::Formula numIdleCycles;
+
+    // number of busy cycles
+    Stats::Formula numBusyCycles;
 
     // number of simulated loads
     Counter numLoad;
     Counter startNumLoad;
 
     // number of idle cycles
-    Stats::Average<> notIdleFraction;
+    Stats::Average notIdleFraction;
     Stats::Formula idleFraction;
 
     // number of cycles stalled for I-cache responses
-    Stats::Scalar<> icacheStallCycles;
+    Stats::Scalar icacheStallCycles;
     Counter lastIcacheStall;
 
     // number of cycles stalled for I-cache retries
-    Stats::Scalar<> icacheRetryCycles;
+    Stats::Scalar icacheRetryCycles;
     Counter lastIcacheRetry;
 
     // number of cycles stalled for D-cache responses
-    Stats::Scalar<> dcacheStallCycles;
+    Stats::Scalar dcacheStallCycles;
     Counter lastDcacheStall;
 
     // number of cycles stalled for D-cache retries
-    Stats::Scalar<> dcacheRetryCycles;
+    Stats::Scalar dcacheRetryCycles;
     Counter lastDcacheRetry;
 
     virtual void serialize(std::ostream &os);
@@ -193,23 +277,9 @@ class BaseSimpleCPU : public BaseCPU
     // These functions are only used in CPU models that split
     // effective address computation from the actual memory access.
     void setEA(Addr EA) { panic("BaseSimpleCPU::setEA() not implemented\n"); }
-    Addr getEA()       { panic("BaseSimpleCPU::getEA() not implemented\n");
+    Addr getEA()        { panic("BaseSimpleCPU::getEA() not implemented\n");
         M5_DUMMY_RETURN}
 
-    void prefetch(Addr addr, unsigned flags)
-    {
-        // need to do this...
-    }
-
-    void writeHint(Addr addr, int size, unsigned flags)
-    {
-        // need to do this...
-    }
-
-    Fault copySrcTranslate(Addr src);
-
-    Fault copy(Addr dest);
-
     // The register accessor methods provide the index of the
     // instruction's operand (e.g., 0 or 1), not the architectural
     // register index, to simplify the implementation of register
@@ -223,73 +293,58 @@ class BaseSimpleCPU : public BaseCPU
 
     uint64_t readIntRegOperand(const StaticInst *si, int idx)
     {
+        numIntRegReads++;
         return thread->readIntReg(si->srcRegIdx(idx));
     }
 
-    FloatReg readFloatRegOperand(const StaticInst *si, int idx, int width)
-    {
-        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
-        return thread->readFloatReg(reg_idx, width);
-    }
-
     FloatReg readFloatRegOperand(const StaticInst *si, int idx)
     {
+        numFpRegReads++;
         int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
         return thread->readFloatReg(reg_idx);
     }
 
-    FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx,
-                                         int width)
-    {
-        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
-        return thread->readFloatRegBits(reg_idx, width);
-    }
-
     FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
     {
+        numFpRegReads++;
         int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
         return thread->readFloatRegBits(reg_idx);
     }
 
     void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
     {
+        numIntRegWrites++;
         thread->setIntReg(si->destRegIdx(idx), val);
     }
 
-    void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val,
-                            int width)
-    {
-        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
-        thread->setFloatReg(reg_idx, val, width);
-    }
-
     void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
     {
+        numFpRegWrites++;
         int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
         thread->setFloatReg(reg_idx, val);
     }
 
-    void setFloatRegOperandBits(const StaticInst *si, int idx,
-                                FloatRegBits val, int width)
-    {
-        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
-        thread->setFloatRegBits(reg_idx, val, width);
-    }
-
     void setFloatRegOperandBits(const StaticInst *si, int idx,
                                 FloatRegBits val)
     {
+        numFpRegWrites++;
         int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
         thread->setFloatRegBits(reg_idx, val);
     }
 
-    uint64_t readPC() { return thread->readPC(); }
-    uint64_t readNextPC() { return thread->readNextPC(); }
-    uint64_t readNextNPC() { return thread->readNextNPC(); }
-
-    void setPC(uint64_t val) { thread->setPC(val); }
-    void setNextPC(uint64_t val) { thread->setNextPC(val); }
-    void setNextNPC(uint64_t val) { thread->setNextNPC(val); }
+    bool readPredicate() { return thread->readPredicate(); }
+    void setPredicate(bool val)
+    {
+        thread->setPredicate(val);
+        if (traceData) {
+            traceData->setPredicate(val);
+        }
+    }
+    TheISA::PCState pcState() { return thread->pcState(); }
+    void pcState(const TheISA::PCState &val) { thread->pcState(val); }
+    Addr instAddr() { return thread->instAddr(); }
+    Addr nextInstAddr() { return thread->nextInstAddr(); }
+    MicroPC microPC() { return thread->microPC(); }
 
     MiscReg readMiscRegNoEffect(int misc_reg)
     {
@@ -298,44 +353,46 @@ class BaseSimpleCPU : public BaseCPU
 
     MiscReg readMiscReg(int misc_reg)
     {
+        numIntRegReads++;
         return thread->readMiscReg(misc_reg);
     }
 
-    void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
-    {
-        return thread->setMiscRegNoEffect(misc_reg, val);
-    }
-
     void setMiscReg(int misc_reg, const MiscReg &val)
     {
+        numIntRegWrites++;
         return thread->setMiscReg(misc_reg, val);
     }
 
-    MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx)
-    {
-        int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
-        return thread->readMiscRegNoEffect(reg_idx);
-    }
-
     MiscReg readMiscRegOperand(const StaticInst *si, int idx)
     {
+        numIntRegReads++;
         int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
         return thread->readMiscReg(reg_idx);
     }
 
-    void setMiscRegOperandNoEffect(const StaticInst *si, int idx, const MiscReg &val)
-    {
-        int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
-        return thread->setMiscRegNoEffect(reg_idx, val);
-    }
-
     void setMiscRegOperand(
             const StaticInst *si, int idx, const MiscReg &val)
     {
+        numIntRegWrites++;
         int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
         return thread->setMiscReg(reg_idx, val);
     }
 
+    void demapPage(Addr vaddr, uint64_t asn)
+    {
+        thread->demapPage(vaddr, asn);
+    }
+
+    void demapInstPage(Addr vaddr, uint64_t asn)
+    {
+        thread->demapInstPage(vaddr, asn);
+    }
+
+    void demapDataPage(Addr vaddr, uint64_t asn)
+    {
+        thread->demapDataPage(vaddr, asn);
+    }
+
     unsigned readStCondFailures() {
         return thread->readStCondFailures();
     }
@@ -344,13 +401,32 @@ class BaseSimpleCPU : public BaseCPU
         thread->setStCondFailures(sc_failures);
     }
 
-#if FULL_SYSTEM
+     MiscReg readRegOtherThread(int regIdx, ThreadID tid = InvalidThreadID)
+     {
+        panic("Simple CPU models do not support multithreaded "
+              "register access.\n");
+     }
+
+     void setRegOtherThread(int regIdx, const MiscReg &val,
+                            ThreadID tid = InvalidThreadID)
+     {
+        panic("Simple CPU models do not support multithreaded "
+              "register access.\n");
+     }
+
+    //Fault CacheOp(uint8_t Op, Addr EA);
+
     Fault hwrei() { return thread->hwrei(); }
-    void ev5_trap(Fault fault) { fault->invoke(tc); }
     bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
-#else
-    void syscall(int64_t callnum) { thread->syscall(callnum); }
-#endif
+
+    void
+    syscall(int64_t callnum)
+    {
+        if (FullSystem)
+            panic("Syscall emulation isn't available in FS mode.\n");
+
+        thread->syscall(callnum);
+    }
 
     bool misspeculating() { return thread->misspeculating(); }
     ThreadContext *tcBase() { return tc; }