MEM: Enable multiple distributed generalized memories
[gem5.git] / src / cpu / inorder / cpu.hh
index fda2e43661abce96ba75478371adbea458095733..d8fe5c0573d44f0a8db00362bae2c14db47411cd 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012 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) 2007 MIPS Technologies, Inc.
  * All rights reserved.
  *
 #include <vector>
 
 #include "arch/isa_traits.hh"
+#include "arch/registers.hh"
+#include "arch/types.hh"
 #include "base/statistics.hh"
-#include "base/timebuf.hh"
-#include "config/full_system.hh"
-#include "cpu/activity.hh"
-#include "cpu/base.hh"
-#include "cpu/simple_thread.hh"
+#include "base/types.hh"
+#include "config/the_isa.hh"
 #include "cpu/inorder/inorder_dyn_inst.hh"
-#include "cpu/inorder/pipeline_traits.hh"
 #include "cpu/inorder/pipeline_stage.hh"
-#include "cpu/inorder/thread_state.hh"
+#include "cpu/inorder/pipeline_traits.hh"
 #include "cpu/inorder/reg_dep_map.hh"
+#include "cpu/inorder/thread_state.hh"
 #include "cpu/o3/dep_graph.hh"
 #include "cpu/o3/rename_map.hh"
+#include "cpu/activity.hh"
+#include "cpu/base.hh"
+#include "cpu/simple_thread.hh"
+#include "cpu/timebuf.hh"
 #include "mem/packet.hh"
 #include "mem/port.hh"
 #include "mem/request.hh"
 #include "sim/eventq.hh"
 #include "sim/process.hh"
 
+class CacheUnit;
 class ThreadContext;
 class MemInterface;
 class MemObject;
@@ -76,7 +92,7 @@ class InOrderCPU : public BaseCPU
     typedef TheISA::FloatReg FloatReg;
     typedef TheISA::FloatRegBits FloatRegBits;
     typedef TheISA::MiscReg MiscReg;
-    typedef TheISA::RegFile RegFile;
+    typedef TheISA::RegIndex RegIndex;
 
     //DynInstPtr TypeDefs
     typedef ThePipeline::DynInstPtr DynInstPtr;
@@ -86,17 +102,37 @@ class InOrderCPU : public BaseCPU
     typedef TimeBuffer<InterStageStruct> StageQueue;
 
     friend class Resource;
-
+    
   public:
     /** Constructs a CPU with the given parameters. */
     InOrderCPU(Params *params);
+    /* Destructor */
+    ~InOrderCPU();
+    
+    /** Return a reference to the data port. */
+    virtual CpuPort &getDataPort() { return dataPort; }
+
+    /** Return a reference to the instruction port. */
+    virtual CpuPort &getInstPort() { return instPort; }
 
     /** CPU ID */
     int cpu_id;
 
+    // SE Mode ASIDs
+    ThreadID asid[ThePipeline::MaxThreads];
+
     /** Type of core that this is */
     std::string coreType;
 
+    // Only need for SE MODE
+    enum ThreadModel {
+        Single,
+        SMT,
+        SwitchOnCacheMiss
+    };
+    
+    ThreadModel threadModel;
+
     int readCpuId() { return cpu_id; }
 
     void setCpuId(int val) { cpu_id = val; }
@@ -114,8 +150,32 @@ class InOrderCPU : public BaseCPU
 
     /** Overall CPU status. */
     Status _status;
-
   private:
+
+    /**
+     * CachePort class for the in-order CPU, interacting with a
+     * specific CacheUnit in the pipeline.
+     */
+    class CachePort : public CpuPort
+    {
+
+      private:
+        /** Pointer to cache unit */
+        CacheUnit *cacheUnit;
+
+      public:
+        /** Default constructor. */
+        CachePort(CacheUnit *_cacheUnit);
+
+      protected:
+
+        /** Timing version of receive */
+        bool recvTiming(PacketPtr pkt);
+
+        /** Handles doing a retry of a failed timing request. */
+        void recvRetry();
+    };
+
     /** Define TickEvent for the CPU */
     class TickEvent : public Event
     {
@@ -131,7 +191,7 @@ class InOrderCPU : public BaseCPU
         void process();
 
         /** Returns the description of the tick event. */
-        const char *description();
+        const char *description() const;
     };
 
     /** The tick event used for scheduling CPU ticks. */
@@ -140,10 +200,8 @@ class InOrderCPU : public BaseCPU
     /** Schedule tick event, regardless of its current state. */
     void scheduleTickEvent(int delay)
     {
-        if (tickEvent.squashed())
-          mainEventQueue.reschedule(&tickEvent, nextCycle(curTick + ticks(delay)));
-        else if (!tickEvent.scheduled())
-          mainEventQueue.schedule(&tickEvent, nextCycle(curTick + ticks(delay)));
+        assert(!tickEvent.scheduled() || tickEvent.squashed());
+        reschedule(&tickEvent, nextCycle(curTick() + ticks(delay)), true);
     }
 
     /** Unschedule tick event, regardless of its current state. */
@@ -162,19 +220,25 @@ class InOrderCPU : public BaseCPU
     // pool event.
     enum CPUEventType {
         ActivateThread,
-        DeallocateThread,
+        ActivateNextReadyThread,
+        DeactivateThread,
+        HaltThread,
         SuspendThread,
-        DisableThreads,
-        EnableThreads,
-        DisableVPEs,
-        EnableVPEs,
         Trap,
-        InstGraduated,
-        SquashAll,
+        Syscall,
+        SquashFromMemStall,
         UpdatePCs,
         NumCPUEvents
     };
 
+    static std::string eventNames[NumCPUEvents];
+
+    enum CPUEventPri {
+        InOrderCPU_Pri                 = Event::CPU_Tick_Pri,
+        Syscall_Pri                    = Event::CPU_Tick_Pri + 9,
+        ActivateNextReadyThread_Pri    = Event::CPU_Tick_Pri + 10
+    };
+
     /** Define CPU Event */
     class CPUEvent : public Event
     {
@@ -183,29 +247,33 @@ class InOrderCPU : public BaseCPU
 
       public:
         CPUEventType cpuEventType;
-        unsigned tid;
-        unsigned vpe;
+        ThreadID tid;
+        DynInstPtr inst;
         Fault fault;
-
+        unsigned vpe;
+        short syscall_num;
+        
       public:
         /** Constructs a CPU event. */
         CPUEvent(InOrderCPU *_cpu, CPUEventType e_type, Fault fault,
-                 unsigned _tid, unsigned _vpe);
+                 ThreadID _tid, DynInstPtr inst, CPUEventPri event_pri);
 
         /** Set Type of Event To Be Scheduled */
-        void setEvent(CPUEventType e_type, Fault _fault, unsigned _tid, unsigned _vpe)
+        void setEvent(CPUEventType e_type, Fault _fault, ThreadID _tid,
+                      DynInstPtr _inst)
         {
             fault = _fault;
             cpuEventType = e_type;
             tid = _tid;
-            vpe = _vpe;
+            inst = _inst;
+            vpe = 0;            
         }
 
-        /** Processes a resource event. */
-        virtual void process();
+        /** Processes a CPU event. */
+        void process();
 
-        /** Returns the description of the resource event. */
-        const char *description();
+        /** Returns the description of the CPU event. */
+        const char *description() const;
 
         /** Schedule Event */
         void scheduleEvent(int delay);
@@ -215,51 +283,53 @@ class InOrderCPU : public BaseCPU
     };
 
     /** Schedule a CPU Event */
-    void scheduleCpuEvent(CPUEventType cpu_event, Fault fault, unsigned tid,
-                          unsigned vpe, unsigned delay = 0);
+    void scheduleCpuEvent(CPUEventType cpu_event, Fault fault, ThreadID tid,
+                          DynInstPtr inst, unsigned delay = 0,
+                          CPUEventPri event_pri = InOrderCPU_Pri);
 
   public:
+
+    /** Width (processing bandwidth) of each stage */
+    int stageWidth;
+
     /** Interface between the CPU and CPU resources. */
     ResourcePool *resPool;
 
-    /** Instruction used to signify that there is no *real* instruction in buffer slot */
+    /** Instruction used to signify that there is no *real* instruction in 
+        buffer slot */
+    DynInstPtr dummyInst[ThePipeline::MaxThreads];
     DynInstPtr dummyBufferInst;
+    DynInstPtr dummyReqInst;
+    DynInstPtr dummyTrapInst[ThePipeline::MaxThreads];
 
     /** Used by resources to signify a denied access to a resource. */
-    ResourceRequest *dummyReq;
-
-    /** Identifies the resource id that identifies a fetch
-     * access unit.
-     */
-    unsigned fetchPortIdx;
-
-    /** Identifies the resource id that identifies a ITB       */
-    unsigned itbIdx;
-
-    /** Identifies the resource id that identifies a data
-     * access unit.
-     */
-    unsigned dataPortIdx;
-
-    /** Identifies the resource id that identifies a DTB       */
-    unsigned dtbIdx;
+    ResourceRequest *dummyReq[ThePipeline::MaxThreads];
 
     /** The Pipeline Stages for the CPU */
     PipelineStage *pipelineStage[ThePipeline::NumStages];
 
     /** Program Counters */
-    TheISA::IntReg PC[ThePipeline::MaxThreads];
-    TheISA::IntReg nextPC[ThePipeline::MaxThreads];
-    TheISA::IntReg nextNPC[ThePipeline::MaxThreads];
+    TheISA::PCState pc[ThePipeline::MaxThreads];
+
+    /** Last Committed PC */
+    TheISA::PCState lastCommittedPC[ThePipeline::MaxThreads];
 
     /** The Register File for the CPU */
-    TheISA::IntRegFile intRegFile[ThePipeline::MaxThreads];;
-    TheISA::FloatRegFile floatRegFile[ThePipeline::MaxThreads];;
-    TheISA::MiscRegFile miscRegFile;
+    union {
+        FloatReg f[ThePipeline::MaxThreads][TheISA::NumFloatRegs];
+        FloatRegBits i[ThePipeline::MaxThreads][TheISA::NumFloatRegs];
+    } floatRegs;
+    TheISA::IntReg intRegs[ThePipeline::MaxThreads][TheISA::NumIntRegs];
+
+    /** ISA state */
+    TheISA::ISA isa[ThePipeline::MaxThreads];
 
     /** Dependency Tracker for Integer & Floating Point Regs */
     RegDepMap archRegDepMap[ThePipeline::MaxThreads];
 
+    /** Register Types Used in Dependency Tracking */
+    enum RegType { IntType, FloatType, MiscType, NumRegTypes};
+
     /** Global communication structure */
     TimeBuffer<TimeStruct> timeBuffer;
 
@@ -269,6 +339,106 @@ class InOrderCPU : public BaseCPU
     TheISA::TLB *getITBPtr();
     TheISA::TLB *getDTBPtr();
 
+    Decoder *getDecoderPtr();
+
+    /** Accessor Type for the SkedCache */
+    typedef uint32_t SkedID;
+
+    /** Cache of Instruction Schedule using the instruction's name as a key */
+    static m5::hash_map<SkedID, ThePipeline::RSkedPtr> skedCache;
+
+    typedef m5::hash_map<SkedID, ThePipeline::RSkedPtr>::iterator SkedCacheIt;
+
+    /** Initialized to last iterator in map, signifying a invalid entry
+        on map searches
+    */
+    SkedCacheIt endOfSkedIt;
+
+    ThePipeline::RSkedPtr frontEndSked;
+    ThePipeline::RSkedPtr faultSked;
+
+    /** Add a new instruction schedule to the schedule cache */
+    void addToSkedCache(DynInstPtr inst, ThePipeline::RSkedPtr inst_sked)
+    {
+        SkedID sked_id = genSkedID(inst);
+        assert(skedCache.find(sked_id) == skedCache.end());
+        skedCache[sked_id] = inst_sked;
+    }
+
+
+    /** Find a instruction schedule */
+    ThePipeline::RSkedPtr lookupSked(DynInstPtr inst)
+    {
+        SkedID sked_id = genSkedID(inst);
+        SkedCacheIt lookup_it = skedCache.find(sked_id);
+
+        if (lookup_it != endOfSkedIt) {
+            return (*lookup_it).second;
+        } else {
+            return NULL;
+        }
+    }
+
+    static const uint8_t INST_OPCLASS                       = 26;
+    static const uint8_t INST_LOAD                          = 25;
+    static const uint8_t INST_STORE                         = 24;
+    static const uint8_t INST_CONTROL                       = 23;
+    static const uint8_t INST_NONSPEC                       = 22;
+    static const uint8_t INST_DEST_REGS                     = 18;
+    static const uint8_t INST_SRC_REGS                      = 14;
+    static const uint8_t INST_SPLIT_DATA                    = 13;
+
+    inline SkedID genSkedID(DynInstPtr inst)
+    {
+        SkedID id = 0;
+        id = (inst->opClass() << INST_OPCLASS) |
+            (inst->isLoad() << INST_LOAD) |
+            (inst->isStore() << INST_STORE) |
+            (inst->isControl() << INST_CONTROL) |
+            (inst->isNonSpeculative() << INST_NONSPEC) |
+            (inst->numDestRegs() << INST_DEST_REGS) |
+            (inst->numSrcRegs() << INST_SRC_REGS) |
+            (inst->splitInst << INST_SPLIT_DATA);
+        return id;
+    }
+
+    ThePipeline::RSkedPtr createFrontEndSked();
+    ThePipeline::RSkedPtr createFaultSked();
+    ThePipeline::RSkedPtr createBackEndSked(DynInstPtr inst);
+
+    class StageScheduler {
+      private:
+        ThePipeline::RSkedPtr rsked;
+        int stageNum;
+        int nextTaskPriority;
+
+      public:
+        StageScheduler(ThePipeline::RSkedPtr _rsked, int stage_num)
+            : rsked(_rsked), stageNum(stage_num),
+              nextTaskPriority(0)
+        { }
+
+        void needs(int unit, int request) {
+            rsked->push(new ScheduleEntry(
+                            stageNum, nextTaskPriority++, unit, request
+                            ));
+        }
+
+        void needs(int unit, int request, int param) {
+            rsked->push(new ScheduleEntry(
+                            stageNum, nextTaskPriority++, unit, request, param
+                            ));
+        }
+    };
+
+  private:
+
+    /** Data port. Note that it has to appear after the resPool. */
+    CachePort dataPort;
+
+    /** Instruction port. Note that it has to appear after the resPool. */
+    CachePort instPort;
+
   public:
 
     /** Registers statistics. */
@@ -282,78 +452,95 @@ class InOrderCPU : public BaseCPU
     /** Initialize the CPU */
     void init();
 
-    /** Reset State in the CPU */
-    void reset();
+    /** HW return from error interrupt. */
+    Fault hwrei(ThreadID tid);
 
-    /** Get a Memory Port */
-    Port* getPort(const std::string &if_name, int idx = 0);
+    bool simPalCheck(int palFunc, ThreadID tid);
 
-    /** trap() - sets up a trap event on the cpuTraps to handle given fault.
-     *  trapCPU() - Traps to handle given fault
-     */
-    void trap(Fault fault, unsigned tid, int delay = 0);
-    void trapCPU(Fault fault, unsigned tid);
+    void checkForInterrupts();
 
-    /** Setup CPU to insert a thread's context */
-    void insertThread(unsigned tid);
+    /** Returns the Fault for any valid interrupt. */
+    Fault getInterrupts();
 
-    /** Remove all of a thread's context from CPU */
-    void removeThread(unsigned tid);
+    /** Processes any an interrupt fault. */
+    void processInterrupts(Fault interrupt);
 
-    /** Add Thread to Active Threads List. */
-    void activateContext(unsigned tid, int delay = 0);
-    void activateThread(unsigned tid);
+    /** Halts the CPU. */
+    void halt() { panic("Halt not implemented!\n"); }
 
-    /** Remove Thread from Active Threads List */
-    void suspendContext(unsigned tid, int delay = 0);
-    void suspendThread(unsigned tid);
+    /** Check if this address is a valid instruction address. */
+    bool validInstAddr(Addr addr) { return true; }
 
-    /** Remove Thread from Active Threads List &&
-     *  Remove Thread Context from CPU.
-     */
-    void deallocateContext(unsigned tid, int delay = 0);
-    void deallocateThread(unsigned tid);
-    void deactivateThread(unsigned tid);
+    /** Check if this address is a valid data address. */
+    bool validDataAddr(Addr addr) { return true; }
 
-    PipelineStage* getPipeStage(int stage_num);
+    /** Schedule a syscall on the CPU */
+    void syscallContext(Fault fault, ThreadID tid, DynInstPtr inst,
+                        int delay = 0);
 
-    int
-    contextId()
-    {
-        hack_once("return a bogus context id");
-        return 0;
-    }
+    /** Executes a syscall.*/
+    void syscall(int64_t callnum, ThreadID tid);
 
-    /** Remove Thread from Active Threads List &&
-     *  Remove Thread Context from CPU.
-     */
-    void haltContext(unsigned tid, int delay = 0);
+    /** Schedule a trap on the CPU */
+    void trapContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay = 0);
 
-    void removePipelineStalls(unsigned tid);
+    /** Perform trap to Handle Given Fault */
+    void trap(Fault fault, ThreadID tid, DynInstPtr inst);
 
-    void squashThreadInPipeline(unsigned tid);
+    /** Schedule thread activation on the CPU */
+    void activateContext(ThreadID tid, int delay = 0);
 
-    /// Notify the CPU to enable a virtual processor element.
-    virtual void enableVirtProcElement(unsigned vpe);
-    void enableVPEs(unsigned vpe);
+    /** Add Thread to Active Threads List. */
+    void activateThread(ThreadID tid);
+
+    /** Activate Thread In Each Pipeline Stage */
+    void activateThreadInPipeline(ThreadID tid);
+    
+    /** Schedule Thread Activation from Ready List */
+    void activateNextReadyContext(int delay = 0);
+
+    /** Add Thread From Ready List to Active Threads List. */
+    void activateNextReadyThread();
 
-    /// Notify the CPU to disable a virtual processor element.
-    virtual void disableVirtProcElement(unsigned tid, unsigned vpe);
-    void disableVPEs(unsigned tid, unsigned vpe);
+    /** Schedule a thread deactivation on the CPU */
+    void deactivateContext(ThreadID tid, int delay = 0);
 
-    /// Notify the CPU that multithreading is enabled.
-    virtual void enableMultiThreading(unsigned vpe);
-    void enableThreads(unsigned vpe);
+    /** Remove from Active Thread List */
+    void deactivateThread(ThreadID tid);
 
-    /// Notify the CPU that multithreading is disabled.
-    virtual void disableMultiThreading(unsigned tid, unsigned vpe);
-    void disableThreads(unsigned tid, unsigned vpe);
+    /** Schedule a thread suspension on the CPU */
+  void suspendContext(ThreadID tid);
 
-    /** Activate a Thread When CPU Resources are Available. */
-    void activateWhenReady(int tid);
+    /** Suspend Thread, Remove from Active Threads List, Add to Suspend List */
+    void suspendThread(ThreadID tid);
 
-    /** Add or Remove a Thread Context in the CPU. */
-    void doContextSwitch();
+    /** Schedule a thread halt on the CPU */
+    void haltContext(ThreadID tid);
+
+    /** Halt Thread, Remove from Active Thread List, Place Thread on Halted 
+     *  Threads List 
+     */
+    void haltThread(ThreadID tid);
+
+    /** squashFromMemStall() - sets up a squash event
+     *  squashDueToMemStall() - squashes pipeline
+     *  @note: maybe squashContext/squashThread would be better?
+     */
+    void squashFromMemStall(DynInstPtr inst, ThreadID tid, int delay = 0);
+    void squashDueToMemStall(int stage_num, InstSeqNum seq_num, ThreadID tid);    
+
+    void removePipelineStalls(ThreadID tid);
+    void squashThreadInPipeline(ThreadID tid);
+    void squashBehindMemStall(int stage_num, InstSeqNum seq_num, ThreadID tid);    
+
+    PipelineStage* getPipeStage(int stage_num);
+
+    int
+    contextId()
+    {
+        hack_once("return a bogus context id");
+        return 0;
+    }
 
     /** Update The Order In Which We Process Threads. */
     void updateThreadPriority();
@@ -363,19 +550,19 @@ class InOrderCPU : public BaseCPU
     { /*pipelineStage[stage_idx]->switchToActive();*/ }
 
     /** Get the current instruction sequence number, and increment it. */
-    InstSeqNum getAndIncrementInstSeq(unsigned tid)
+    InstSeqNum getAndIncrementInstSeq(ThreadID tid)
     { return globalSeqNum[tid]++; }
 
     /** Get the current instruction sequence number, and increment it. */
-    InstSeqNum nextInstSeqNum(unsigned tid)
+    InstSeqNum nextInstSeqNum(ThreadID tid)
     { return globalSeqNum[tid]; }
 
     /** Increment Instruction Sequence Number */
-    void incrInstSeqNum(unsigned tid)
+    void incrInstSeqNum(ThreadID tid)
     { globalSeqNum[tid]++; }
 
     /** Set Instruction Sequence Number */
-    void setInstSeqNum(unsigned tid, InstSeqNum seq_num)
+    void setInstSeqNum(ThreadID tid, InstSeqNum seq_num)
     {
         globalSeqNum[tid] = seq_num;
     }
@@ -383,105 +570,112 @@ class InOrderCPU : public BaseCPU
     /** Get & Update Next Event Number */
     InstSeqNum getNextEventNum()
     {
+#ifdef DEBUG
         return cpuEventNum++;
+#else
+        return 0;
+#endif
     }
 
-    /** Get instruction asid. */
-    int getInstAsid(unsigned tid)
-    { return thread[tid]->getInstAsid(); }
+    /** Register file accessors  */
+    uint64_t readIntReg(RegIndex reg_idx, ThreadID tid);
 
-    /** Get data asid. */
-    int getDataAsid(unsigned tid)
-    { return thread[tid]->getDataAsid(); }
+    FloatReg readFloatReg(RegIndex reg_idx, ThreadID tid);
 
-    /** Register file accessors  */
-    uint64_t readIntReg(int reg_idx, unsigned tid);
+    FloatRegBits readFloatRegBits(RegIndex reg_idx, ThreadID tid);
 
-    FloatReg readFloatReg(int reg_idx, unsigned tid,
-                          int width = TheISA::SingleWidth);
+    void setIntReg(RegIndex reg_idx, uint64_t val, ThreadID tid);
 
-    FloatRegBits readFloatRegBits(int reg_idx, unsigned tid,
-                                  int width = TheISA::SingleWidth);
+    void setFloatReg(RegIndex reg_idx, FloatReg val, ThreadID tid);
 
-    void setIntReg(int reg_idx, uint64_t val, unsigned tid);
+    void setFloatRegBits(RegIndex reg_idx, FloatRegBits val,  ThreadID tid);
 
-    void setFloatReg(int reg_idx, FloatReg val,  unsigned tid,
-                     int width = TheISA::SingleWidth);
+    RegType inline getRegType(RegIndex reg_idx)
+    {
+        if (reg_idx < TheISA::FP_Base_DepTag)
+            return IntType;
+        else if (reg_idx < TheISA::Ctrl_Base_DepTag)
+            return FloatType;
+        else
+            return MiscType;
+    }
 
-    void setFloatRegBits(int reg_idx, FloatRegBits val,  unsigned tid,
-                         int width = TheISA::SingleWidth);
+    RegIndex flattenRegIdx(RegIndex reg_idx, RegType &reg_type, ThreadID tid);
 
     /** Reads a miscellaneous register. */
-    MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid = 0);
+    MiscReg readMiscRegNoEffect(int misc_reg, ThreadID tid = 0);
 
     /** Reads a misc. register, including any side effects the read
      * might have as defined by the architecture.
      */
-    MiscReg readMiscReg(int misc_reg, unsigned tid = 0);
+    MiscReg readMiscReg(int misc_reg, ThreadID tid = 0);
 
     /** Sets a miscellaneous register. */
-    void setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid = 0);
+    void setMiscRegNoEffect(int misc_reg, const MiscReg &val,
+                            ThreadID tid = 0);
 
     /** Sets a misc. register, including any side effects the write
      * might have as defined by the architecture.
      */
-    void setMiscReg(int misc_reg, const MiscReg &val, unsigned tid = 0);
+    void setMiscReg(int misc_reg, const MiscReg &val, ThreadID tid = 0);
 
     /** Reads a int/fp/misc reg. from another thread depending on ISA-defined
      *  target thread
      */
-    uint64_t readRegOtherThread(unsigned misc_reg, unsigned tid = -1);
+    uint64_t readRegOtherThread(unsigned misc_reg,
+                                ThreadID tid = InvalidThreadID);
 
     /** Sets a int/fp/misc reg. from another thread depending on an ISA-defined
      * target thread
      */
-    void setRegOtherThread(unsigned misc_reg, const MiscReg &val, unsigned tid);
+    void setRegOtherThread(unsigned misc_reg, const MiscReg &val,
+                           ThreadID tid);
 
     /** Reads the commit PC of a specific thread. */
-    uint64_t readPC(unsigned tid);
+    TheISA::PCState
+    pcState(ThreadID tid)
+    {
+        return pc[tid];
+    }
 
     /** Sets the commit PC of a specific thread. */
-    void setPC(Addr new_PC, unsigned tid);
-
-    /** Reads the next PC of a specific thread. */
-    uint64_t readNextPC(unsigned tid);
-
-    /** Sets the next PC of a specific thread. */
-    void setNextPC(uint64_t val, unsigned tid);
-
-    /** Reads the next NPC of a specific thread. */
-    uint64_t readNextNPC(unsigned tid);
+    void
+    pcState(const TheISA::PCState &newPC, ThreadID tid)
+    {
+        pc[tid] = newPC;
+    }
 
-    /** Sets the next NPC of a specific thread. */
-    void setNextNPC(uint64_t val, unsigned tid);
+    Addr instAddr(ThreadID tid) { return pc[tid].instAddr(); }
+    Addr nextInstAddr(ThreadID tid) { return pc[tid].nextInstAddr(); }
+    MicroPC microPC(ThreadID tid) { return pc[tid].microPC(); }
 
     /** Function to add instruction onto the head of the list of the
      *  instructions.  Used when new instructions are fetched.
      */
-    ListIt addInst(DynInstPtr &inst);
+    ListIt addInst(DynInstPtr inst);
+
+    /** Find instruction on instruction list */
+    ListIt findInst(InstSeqNum seq_num, ThreadID tid);
 
     /** Function to tell the CPU that an instruction has completed. */
-    void instDone(DynInstPtr inst, unsigned tid);
+    void instDone(DynInstPtr inst, ThreadID tid);
 
     /** Add Instructions to the CPU Remove List*/
-    void addToRemoveList(DynInstPtr &inst);
+    void addToRemoveList(DynInstPtr inst);
 
     /** Remove an instruction from CPU */
-    void removeInst(DynInstPtr &inst);
+    void removeInst(DynInstPtr inst);
 
     /** Remove all instructions younger than the given sequence number. */
-    void removeInstsUntil(const InstSeqNum &seq_num,unsigned tid);
+    void removeInstsUntil(const InstSeqNum &seq_num,ThreadID tid);
 
     /** Removes the instruction pointed to by the iterator. */
-    inline void squashInstIt(const ListIt &instIt, const unsigned &tid);
+    inline void squashInstIt(const ListIt inst_it, ThreadID tid);
 
     /** Cleans up all instructions on the instruction remove list. */
     void cleanUpRemovedInsts();
 
-    /** Cleans up all instructions on the request remove list. */
-    void cleanUpRemovedReqs();
-
-    /** Cleans up all instructions on the CPU event remove list. */
+    /** Cleans up all events on the CPU event remove list. */
     void cleanUpRemovedEvents();
 
     /** Debug function to print all instructions on the list. */
@@ -490,15 +684,14 @@ class InOrderCPU : public BaseCPU
     /** Forwards an instruction read to the appropriate data
      *  resource (indexes into Resource Pool thru "dataPortIdx")
      */
-    Fault read(DynInstPtr inst);
+    Fault read(DynInstPtr inst, Addr addr,
+               uint8_t *data, unsigned size, unsigned flags);
 
     /** Forwards an instruction write. to the appropriate data
      *  resource (indexes into Resource Pool thru "dataPortIdx")
      */
-    Fault write(DynInstPtr inst);
-
-    /** Executes a syscall.*/
-    void syscall(int64_t callnum, int tid);
+    Fault write(DynInstPtr inst, uint8_t *data, unsigned size,
+                Addr addr, unsigned flags, uint64_t *write_res = NULL);
 
   public:
     /** Per-Thread List of all the instructions in flight. */
@@ -509,10 +702,7 @@ class InOrderCPU : public BaseCPU
      */
     std::queue<ListIt> removeList;
 
-    /** List of all the resource requests that will be removed at the end of this
-     *  cycle.
-     */
-    std::queue<ResourceRequest*> reqRemoveList;
+    bool trapPending[ThePipeline::MaxThreads];
 
     /** List of all the cpu event requests that will be removed at the end of
      *  the current cycle.
@@ -538,24 +728,25 @@ class InOrderCPU : public BaseCPU
     /** Last Cycle that the CPU squashed instruction end. */
     Tick lastSquashCycle[ThePipeline::MaxThreads];
 
-    std::list<unsigned> fetchPriorityList;
+    std::list<ThreadID> fetchPriorityList;
 
   protected:
     /** Active Threads List */
-    std::list<unsigned> activeThreads;
+    std::list<ThreadID> activeThreads;
 
-    /** Current Threads List */
-    std::list<unsigned> currentThreads;
+    /** Ready Threads List */
+    std::list<ThreadID> readyThreads;
 
     /** Suspended Threads List */
-    std::list<unsigned> suspendedThreads;
+    std::list<ThreadID> suspendedThreads;
+
+    /** Halted Threads List */
+    std::list<ThreadID> haltedThreads;
 
-    /** Thread Status Functions (Unused Currently) */
-    bool isThreadInCPU(unsigned tid);
-    bool isThreadActive(unsigned tid);
-    bool isThreadSuspended(unsigned tid);
-    void addToCurrentThreads(unsigned tid);
-    void removeFromCurrentThreads(unsigned tid);
+    /** Thread Status Functions */
+    bool isThreadActive(ThreadID tid);
+    bool isThreadReady(ThreadID tid);
+    bool isThreadSuspended(ThreadID tid);
 
   private:
     /** The activity recorder; used to tell if the CPU has any
@@ -565,11 +756,22 @@ class InOrderCPU : public BaseCPU
     ActivityRecorder activityRec;
 
   public:
-    void readFunctional(Addr addr, uint32_t &buffer);
-
     /** Number of Active Threads in the CPU */
-    int numActiveThreads() { return activeThreads.size(); }
+    ThreadID numActiveThreads() { return activeThreads.size(); }
 
+    /** Thread id of active thread
+     *  Only used for SwitchOnCacheMiss model. 
+     *  Assumes only 1 thread active
+     */
+    ThreadID activeThreadId() 
+    { 
+        if (numActiveThreads() > 0)
+            return activeThreads.front();
+        else
+            return InvalidThreadID;
+    }
+    
+     
     /** Records that there was time buffer activity this cycle. */
     void activityThisCycle() { activityRec.activity(); }
 
@@ -584,48 +786,70 @@ class InOrderCPU : public BaseCPU
     /** Wakes the CPU, rescheduling the CPU if it's not already active. */
     void wakeCPU();
 
-    /** Gets a free thread id. Use if thread ids change across system. */
-    int getFreeTid();
+    virtual void wakeup();
 
-    // LL/SC debug functionality
+    /* LL/SC debug functionality
     unsigned stCondFails;
-    unsigned readStCondFailures() { return stCondFails; }
-    unsigned setStCondFailures(unsigned st_fails) { return stCondFails = st_fails; }
+
+    unsigned readStCondFailures() 
+    { return stCondFails; }
+
+    unsigned setStCondFailures(unsigned st_fails) 
+    { return stCondFails = st_fails; }
+    */
 
     /** Returns a pointer to a thread context. */
-    ThreadContext *tcBase(unsigned tid = 0)
+    ThreadContext *tcBase(ThreadID tid = 0)
     {
         return thread[tid]->getTC();
     }
 
     /** Count the Total Instructions Committed in the CPU. */
-    virtual Counter totalInstructions() const
+    virtual Counter totalInsts() const
     {
         Counter total(0);
 
-        for (int i=0; i < thread.size(); i++)
-            total += thread[i]->numInst;
+        for (ThreadID tid = 0; tid < (ThreadID)thread.size(); tid++)
+            total += thread[tid]->numInst;
 
         return total;
     }
 
+    /** Count the Total Ops Committed in the CPU. */
+    virtual Counter totalOps() const
+    {
+        Counter total(0);
+
+        for (ThreadID tid = 0; tid < (ThreadID)thread.size(); tid++)
+            total += thread[tid]->numOp;
+
+        return total;
+    }
+
+    /** Pointer to the system. */
+    System *system;
+
     /** The global sequence number counter. */
     InstSeqNum globalSeqNum[ThePipeline::MaxThreads];
 
+#ifdef DEBUG
     /** The global event number counter. */
     InstSeqNum cpuEventNum;
 
-    /** Counter of how many stages have completed switching out. */
-    int switchCount;
+    /** Number of resource requests active in CPU **/
+    unsigned resReqCount;
+#endif
 
-    /** Pointers to all of the threads in the CPU. */
-    std::vector<Thread *> thread;
+    Addr lockAddr;
+
+    /** Temporary fix for the lock flag, works in the UP case. */
+    bool lockFlag;
 
-    /** Pointer to the icache interface. */
-    MemInterface *icacheInterface;
+    /** Counter of how many stages have completed draining */
+    int drainCount;
 
-    /** Pointer to the dcache interface. */
-    MemInterface *dcacheInterface;
+    /** Pointers to all of the threads in the CPU. */
+    std::vector<Thread *> thread;
 
     /** Whether or not the CPU should defer its registration. */
     bool deferRegistration;
@@ -633,21 +857,14 @@ class InOrderCPU : public BaseCPU
     /** Per-Stage Instruction Tracing */
     bool stageTracing;
 
-    /** Is there a context switch pending? */
-    bool contextSwitch;
-
-    /** Threads Scheduled to Enter CPU */
-    std::list<int> cpuWaitList;
-
     /** The cycle that the CPU was last running, used for statistics. */
     Tick lastRunningCycle;
 
-    /** Number of Threads the CPU can process */
-    unsigned numThreads;
-
-    /** Number of Virtual Processors the CPU can process */
-    unsigned numVirtProcs;
-
+    void updateContextSwitchStats();    
+    unsigned instsPerSwitch;    
+    Stats::Average instsPerCtxtSwitch;    
+    Stats::Scalar numCtxtSwitches;
+    
     /** Update Thread , used for statistic purposes*/
     inline void tickThreadStats();
 
@@ -660,12 +877,32 @@ class InOrderCPU : public BaseCPU
     /** Stat for total number of times the CPU is descheduled. */
     Stats::Scalar timesIdled;
 
-    /** Stat for total number of cycles the CPU spends descheduled. */
+    /** Stat for total number of cycles the CPU spends descheduled or no
+     *  stages active.
+     */
     Stats::Scalar idleCycles;
 
+    /** Stat for total number of cycles the CPU is active. */
+    Stats::Scalar runCycles;
+
+    /** Percentage of cycles a stage was active */
+    Stats::Formula activity;
+
+    /** Instruction Mix Stats */
+    Stats::Scalar comLoads;
+    Stats::Scalar comStores;
+    Stats::Scalar comBranches;
+    Stats::Scalar comNops;
+    Stats::Scalar comNonSpec;
+    Stats::Scalar comInts;
+    Stats::Scalar comFloats;
+
     /** Stat for the number of committed instructions per thread. */
     Stats::Vector committedInsts;
 
+    /** Stat for the number of committed ops per thread. */
+    Stats::Vector committedOps;
+
     /** Stat for the number of committed instructions per thread. */
     Stats::Vector smtCommittedInsts;