add in the files to the SConscript for split caches
[gem5.git] / cpu / exec_context.hh
index 6964b35b83c8a9da51e498aeb61f2e84c8a3b801..6a17951f95bd693473bec2006cf58136026f452b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef __EXEC_CONTEXT_HH__
-#define __EXEC_CONTEXT_HH__
+#ifndef __CPU_EXEC_CONTEXT_HH__
+#define __CPU_EXEC_CONTEXT_HH__
 
+#include "config/full_system.hh"
+#include "mem/functional/functional.hh"
+#include "mem/mem_req.hh"
 #include "sim/host.hh"
-#include "targetarch/mem_req.hh"
+#include "sim/serialize.hh"
+#include "targetarch/byte_swap.hh"
 
 // forward declaration: see functional_memory.hh
 class FunctionalMemory;
 class PhysicalMemory;
 class BaseCPU;
 
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
 
+#include "sim/system.hh"
 #include "targetarch/alpha_memory.hh"
-class MemoryController;
 
-#include "kern/tru64/kernel_stats.hh"
-#include "sim/system.hh"
+class MemoryController;
+class StaticInstBase;
+namespace Kernel { class Binning; class Statistics; }
 
 #else // !FULL_SYSTEM
 
-#include "sim/prog.hh"
+#include "sim/process.hh"
 
 #endif // FULL_SYSTEM
 
@@ -60,19 +65,46 @@ class MemoryController;
 class ExecContext
 {
   public:
-    enum Status { Unallocated, Active, Suspended, Halted };
+    enum Status
+    {
+        /// Initialized but not running yet.  All CPUs start in
+        /// this state, but most transition to Active on cycle 1.
+        /// In MP or SMT systems, non-primary contexts will stay
+        /// in this state until a thread is assigned to them.
+        Unallocated,
+
+        /// Running.  Instructions should be executed only when
+        /// the context is in this state.
+        Active,
+
+        /// Temporarily inactive.  Entered while waiting for
+        /// synchronization, etc.
+        Suspended,
+
+        /// Permanently shut down.  Entered when target executes
+        /// m5exit pseudo-instruction.  When all contexts enter
+        /// this state, the simulation will terminate.
+        Halted
+    };
 
   private:
     Status _status;
 
   public:
     Status status() const { return _status; }
-    void setStatus(Status new_status);
 
-#ifdef FULL_SYSTEM
-  public:
-    KernelStats kernelStats;
-#endif
+    /// Set the status to Active.  Optional delay indicates number of
+    /// cycles to wait before beginning execution.
+    void activate(int delay = 1);
+
+    /// Set the status to Suspended.
+    void suspend();
+
+    /// Set the status to Unallocated.
+    void deallocate();
+
+    /// Set the status to Halted.
+    void halt();
 
   public:
     RegFile regs;      // correct-path register context
@@ -80,23 +112,34 @@ class ExecContext
     // pointer to CPU associated with this context
     BaseCPU *cpu;
 
+    // Current instruction
+    MachInst inst;
+
     // Index of hardware thread context on the CPU that this represents.
     int thread_num;
 
-#ifdef FULL_SYSTEM
+    // ID of this context w.r.t. the System or Process object to which
+    // it belongs.  For full-system mode, this is the system CPU ID.
+    int cpu_id;
 
+#if FULL_SYSTEM
     FunctionalMemory *mem;
-    AlphaItb *itb;
-    AlphaDtb *dtb;
-    int cpu_id;
+    AlphaITB *itb;
+    AlphaDTB *dtb;
     System *system;
 
     // the following two fields are redundant, since we can always
     // look them up through the system pointer, but we'll leave them
     // here for now for convenience
-    MemoryController *memCtrl;
+    MemoryController *memctrl;
     PhysicalMemory *physmem;
 
+    Kernel::Binning *kernelBinning;
+    Kernel::Statistics *kernelStats;
+    bool bin;
+    bool fnbin;
+    void execute(const StaticInstBase *inst);
+
 #else
     Process *process;
 
@@ -109,12 +152,24 @@ class ExecContext
 
 #endif
 
+    /**
+     * Temporary storage to pass the source address from copy_load to
+     * copy_store.
+     * @todo Remove this temporary when we have a better way to do it.
+     */
+    Addr copySrcAddr;
+    /**
+     * Temp storage for the physical source address of a copy.
+     * @todo Remove this temporary when we have a better way to do it.
+     */
+    Addr copySrcPhysAddr;
+
 
     /*
      * number of executed instructions, for matching with syscall trace
      * points in EIO files.
      */
-    Counter func_exe_insn;
+    Counter func_exe_inst;
 
     //
     // Count failed store conditionals so we can warn of apparent
@@ -122,41 +177,44 @@ class ExecContext
     unsigned storeCondFailures;
 
     // constructor: initialize context from given process structure
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
     ExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
-                AlphaItb *_itb, AlphaDtb *_dtb, FunctionalMemory *_dem,
-                int _cpu_id);
+                AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem);
 #else
     ExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid);
     ExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
                 int _asid);
 #endif
-    virtual ~ExecContext() {}
+    virtual ~ExecContext();
+
+    virtual void takeOverFrom(ExecContext *oldContext);
 
     void regStats(const std::string &name);
 
-#ifdef FULL_SYSTEM
+    void serialize(std::ostream &os);
+    void unserialize(Checkpoint *cp, const std::string &section);
+
+#if FULL_SYSTEM
     bool validInstAddr(Addr addr) { return true; }
     bool validDataAddr(Addr addr) { return true; }
-    int getInstAsid() { return ITB_ASN_ASN(regs.ipr[TheISA::IPR_ITB_ASN]); }
-    int getDataAsid() { return DTB_ASN_ASN(regs.ipr[TheISA::IPR_DTB_ASN]); }
+    int getInstAsid() { return regs.instAsid(); }
+    int getDataAsid() { return regs.dataAsid(); }
 
-    Fault translateInstReq(MemReqPtr req)
+    Fault translateInstReq(MemReqPtr &req)
     {
         return itb->translate(req);
     }
 
-    Fault translateDataReadReq(MemReqPtr req)
+    Fault translateDataReadReq(MemReqPtr &req)
     {
         return dtb->translate(req, false);
     }
 
-    Fault translateDataWriteReq(MemReqPtr req)
+    Fault translateDataWriteReq(MemReqPtr &req)
     {
         return dtb->translate(req, true);
     }
 
-
 #else
     bool validInstAddr(Addr addr)
     { return process->validInstAddr(addr); }
@@ -167,7 +225,7 @@ class ExecContext
     int getInstAsid() { return asid; }
     int getDataAsid() { return asid; }
 
-    Fault dummyTranslation(MemReqPtr req)
+    Fault dummyTranslation(MemReqPtr &req)
     {
 #if 0
         assert((req->vaddr >> 48 & 0xffff) == 0);
@@ -178,15 +236,15 @@ class ExecContext
         req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
         return No_Fault;
     }
-    Fault translateInstReq(MemReqPtr req)
+    Fault translateInstReq(MemReqPtr &req)
     {
         return dummyTranslation(req);
     }
-    Fault translateDataReadReq(MemReqPtr req)
+    Fault translateDataReadReq(MemReqPtr &req)
     {
         return dummyTranslation(req);
     }
-    Fault translateDataWriteReq(MemReqPtr req)
+    Fault translateDataWriteReq(MemReqPtr &req)
     {
         return dummyTranslation(req);
     }
@@ -194,22 +252,26 @@ class ExecContext
 #endif
 
     template <class T>
-    Fault read(MemReqPtr req, T& data)
+    Fault read(MemReqPtr &req, T &data)
     {
-#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM)
+#if FULL_SYSTEM && defined(TARGET_ALPHA)
         if (req->flags & LOCKED) {
             MiscRegFile *cregs = &req->xc->regs.miscRegs;
             cregs->lock_addr = req->paddr;
             cregs->lock_flag = true;
         }
 #endif
-        return mem->read(req, data);
+
+        Fault error;
+        error = mem->read(req, data);
+        data = gtoh(data);
+        return error;
     }
 
     template <class T>
-    Fault write(MemReqPtr req, T& data)
+    Fault write(MemReqPtr &req, T &data)
     {
-#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM)
+#if FULL_SYSTEM && defined(TARGET_ALPHA)
 
         MiscRegFile *cregs;
 
@@ -218,7 +280,7 @@ class ExecContext
             cregs = &req->xc->regs.miscRegs;
 
             if (req->flags & UNCACHEABLE) {
-                // Don't update result register (see machine.def)
+                // Don't update result register (see stq_c in isa_desc)
                 req->result = 2;
                 req->xc->storeCondFailures = 0;//Needed? [RGD]
             } else {
@@ -239,26 +301,37 @@ class ExecContext
             }
         }
 
-        // Need to clear any locked flags on other proccessors for this
-        // address
-        // Only do this for succsful Store Conditionals and all other
-        // stores (WH64?)
-        // Unsuccesful Store Conditionals would have returned above,
-        // and wouldn't fall through
-        for(int i = 0; i < system->xcvec.size(); i++){
-            cregs = &system->xcvec[i]->regs.miscRegs;
-            if((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) {
+        // Need to clear any locked flags on other proccessors for
+        // this address.  Only do this for succsful Store Conditionals
+        // and all other stores (WH64?).  Unsuccessful Store
+        // Conditionals would have returned above, and wouldn't fall
+        // through.
+        for (int i = 0; i < system->execContexts.size(); i++){
+            cregs = &system->execContexts[i]->regs.miscRegs;
+            if ((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) {
                 cregs->lock_flag = false;
             }
         }
 
 #endif
-        return mem->write(req, data);
+        return mem->write(req, (T)htog(data));
     }
 
     virtual bool misspeculating();
 
 
+    MachInst getInst() { return inst; }
+
+    void setInst(MachInst new_inst)
+    {
+        inst = new_inst;
+    }
+
+    Fault instRead(MemReqPtr &req)
+    {
+        return mem->read(req, inst);
+    }
+
     //
     // New accessors for new decoder.
     //
@@ -332,15 +405,54 @@ class ExecContext
         regs.miscRegs.fpcr = val;
     }
 
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
     uint64_t readIpr(int idx, Fault &fault);
     Fault setIpr(int idx, uint64_t val);
+    int readIntrFlag() { return regs.intrflag; }
+    void setIntrFlag(int val) { regs.intrflag = val; }
     Fault hwrei();
+    bool inPalMode() { return AlphaISA::PcPAL(regs.pc); }
     void ev5_trap(Fault fault);
     bool simPalCheck(int palFunc);
 #endif
 
-#ifndef FULL_SYSTEM
+    /** Meant to be more generic trap function to be
+     *  called when an instruction faults.
+     *  @param fault The fault generated by executing the instruction.
+     *  @todo How to do this properly so it's dependent upon ISA only?
+     */
+
+    void trap(Fault fault);
+
+#if !FULL_SYSTEM
+    IntReg getSyscallArg(int i)
+    {
+        return regs.intRegFile[ArgumentReg0 + i];
+    }
+
+    // used to shift args for indirect syscall
+    void setSyscallArg(int i, IntReg val)
+    {
+        regs.intRegFile[ArgumentReg0 + i] = val;
+    }
+
+    void setSyscallReturn(SyscallReturn return_value)
+    {
+        // check for error condition.  Alpha syscall convention is to
+        // indicate success/failure in reg a3 (r19) and put the
+        // return value itself in the standard return value reg (v0).
+        const int RegA3 = 19;  // only place this is used
+        if (return_value.successful()) {
+            // no error
+            regs.intRegFile[RegA3] = 0;
+            regs.intRegFile[ReturnValueReg] = return_value.value();
+        } else {
+            // got an error, return details
+            regs.intRegFile[RegA3] = (IntReg) -1;
+            regs.intRegFile[ReturnValueReg] = -return_value.value();
+        }
+    }
+
     void syscall()
     {
         process->syscall(this);
@@ -356,4 +468,4 @@ ExecContext::misspeculating()
     return false;
 }
 
-#endif // __EXEC_CONTEXT_HH__
+#endif // __CPU_EXEC_CONTEXT_HH__