arch, cpu: Add support for flattening misc register indexes.
[gem5.git] / src / cpu / inorder / cpu.hh
index 42d8da18c5cc803da710050fb1ecb015b067e2c9..1183f6fc9ab29876b2b80fd653a132c6978d5504 100644 (file)
@@ -1,4 +1,17 @@
 /*
+ * Copyright (c) 2012-2013 ARM Limited
+ * Copyright (c) 2013 Advanced Micro Devices, Inc.
+ * 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.
  *
@@ -43,7 +56,6 @@
 #include "arch/types.hh"
 #include "base/statistics.hh"
 #include "base/types.hh"
-#include "config/full_system.hh"
 #include "config/the_isa.hh"
 #include "cpu/inorder/inorder_dyn_inst.hh"
 #include "cpu/inorder/pipeline_stage.hh"
@@ -54,6 +66,7 @@
 #include "cpu/o3/rename_map.hh"
 #include "cpu/activity.hh"
 #include "cpu/base.hh"
+#include "cpu/reg_class.hh"
 #include "cpu/simple_thread.hh"
 #include "cpu/timebuf.hh"
 #include "mem/packet.hh"
@@ -62,6 +75,7 @@
 #include "sim/eventq.hh"
 #include "sim/process.hh"
 
+class CacheUnit;
 class ThreadContext;
 class MemInterface;
 class MemObject;
@@ -79,6 +93,7 @@ class InOrderCPU : public BaseCPU
     typedef TheISA::IntReg IntReg;
     typedef TheISA::FloatReg FloatReg;
     typedef TheISA::FloatRegBits FloatRegBits;
+    typedef TheISA::CCReg CCReg;
     typedef TheISA::MiscReg MiscReg;
     typedef TheISA::RegIndex RegIndex;
 
@@ -97,6 +112,14 @@ class InOrderCPU : public BaseCPU
     /* Destructor */
     ~InOrderCPU();
     
+    void verifyMemoryMode() const;
+
+    /** Return a reference to the data port. */
+    virtual MasterPort &getDataPort() { return dataPort; }
+
+    /** Return a reference to the instruction port. */
+    virtual MasterPort &getInstPort() { return instPort; }
+
     /** CPU ID */
     int cpu_id;
 
@@ -133,6 +156,34 @@ 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 MasterPort
+    {
+
+      private:
+        /** Pointer to cache unit */
+        CacheUnit *cacheUnit;
+
+      public:
+        /** Default constructor. */
+        CachePort(CacheUnit *_cacheUnit, const std::string& name);
+
+      protected:
+
+        /** Timing version of receive */
+        bool recvTimingResp(PacketPtr pkt);
+
+        /** Handles doing a retry of a failed timing request. */
+        void recvRetry();
+
+        /** Ignoring snoops for now. */
+        void recvTimingSnoopReq(PacketPtr pkt) { }
+    };
+
     /** Define TickEvent for the CPU */
     class TickEvent : public Event
     {
@@ -148,17 +199,17 @@ 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. */
     TickEvent tickEvent;
 
     /** Schedule tick event, regardless of its current state. */
-    void scheduleTickEvent(int delay)
+    void scheduleTickEvent(Cycles delay)
     {
         assert(!tickEvent.scheduled() || tickEvent.squashed());
-        reschedule(&tickEvent, nextCycle(curTick() + ticks(delay)), true);
+        reschedule(&tickEvent, clockEdge(delay), true);
     }
 
     /** Unschedule tick event, regardless of its current state. */
@@ -182,7 +233,7 @@ class InOrderCPU : public BaseCPU
         HaltThread,
         SuspendThread,
         Trap,
-        InstGraduated,
+        Syscall,
         SquashFromMemStall,
         UpdatePCs,
         NumCPUEvents
@@ -190,6 +241,12 @@ class InOrderCPU : public BaseCPU
 
     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
     {
@@ -202,11 +259,12 @@ class InOrderCPU : public BaseCPU
         DynInstPtr inst;
         Fault fault;
         unsigned vpe;
+        short syscall_num;
         
       public:
         /** Constructs a CPU event. */
         CPUEvent(InOrderCPU *_cpu, CPUEventType e_type, Fault fault,
-                 ThreadID _tid, DynInstPtr inst, unsigned event_pri_offset);
+                 ThreadID _tid, DynInstPtr inst, CPUEventPri event_pri);
 
         /** Set Type of Event To Be Scheduled */
         void setEvent(CPUEventType e_type, Fault _fault, ThreadID _tid,
@@ -223,10 +281,10 @@ class InOrderCPU : public BaseCPU
         void process();
 
         /** Returns the description of the CPU event. */
-        const char *description();
+        const char *description() const;
 
         /** Schedule Event */
-        void scheduleEvent(int delay);
+        void scheduleEvent(Cycles delay);
 
         /** Unschedule This Event */
         void unscheduleEvent();
@@ -234,10 +292,14 @@ class InOrderCPU : public BaseCPU
 
     /** Schedule a CPU Event */
     void scheduleCpuEvent(CPUEventType cpu_event, Fault fault, ThreadID tid,
-                          DynInstPtr inst, unsigned delay = 0,
-                          unsigned event_pri_offset = 0);
+                          DynInstPtr inst, Cycles delay = Cycles(0),
+                          CPUEventPri event_pri = InOrderCPU_Pri);
 
   public:
+
+    /** Width (processing bandwidth) of each stage */
+    int stageWidth;
+
     /** Interface between the CPU and CPU resources. */
     ResourcePool *resPool;
 
@@ -246,44 +308,32 @@ class InOrderCPU : public BaseCPU
     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[ThePipeline::MaxThreads];
 
-    /** 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;
-
     /** The Pipeline Stages for the CPU */
     PipelineStage *pipelineStage[ThePipeline::NumStages];
 
-    /** Width (processing bandwidth) of each stage */
-    int stageWidth;
-
     /** Program Counters */
     TheISA::PCState pc[ThePipeline::MaxThreads];
 
+    /** Last Committed PC */
+    TheISA::PCState lastCommittedPC[ThePipeline::MaxThreads];
+
     /** The Register File for the CPU */
     union {
         FloatReg f[ThePipeline::MaxThreads][TheISA::NumFloatRegs];
         FloatRegBits i[ThePipeline::MaxThreads][TheISA::NumFloatRegs];
     } floatRegs;
     TheISA::IntReg intRegs[ThePipeline::MaxThreads][TheISA::NumIntRegs];
+#ifdef ISA_HAS_CC_REGS
+    TheISA::CCReg ccRegs[ThePipeline::MaxThreads][TheISA::NumCCRegs];
+#endif
 
     /** ISA state */
-    TheISA::ISA isa[ThePipeline::MaxThreads];
+    std::vector<TheISA::ISA *> isa;
 
     /** Dependency Tracker for Integer & Floating Point Regs */
     RegDepMap archRegDepMap[ThePipeline::MaxThreads];
@@ -297,6 +347,8 @@ class InOrderCPU : public BaseCPU
     TheISA::TLB *getITBPtr();
     TheISA::TLB *getDTBPtr();
 
+    TheISA::Decoder *getDecoderPtr(unsigned tid);
+
     /** Accessor Type for the SkedCache */
     typedef uint32_t SkedID;
 
@@ -311,6 +363,7 @@ class InOrderCPU : public BaseCPU
     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)
@@ -341,6 +394,7 @@ class InOrderCPU : public BaseCPU
     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)
     {
@@ -351,11 +405,13 @@ class InOrderCPU : public BaseCPU
             (inst->isControl() << INST_CONTROL) |
             (inst->isNonSpeculative() << INST_NONSPEC) |
             (inst->numDestRegs() << INST_DEST_REGS) |
-            (inst->numSrcRegs() << INST_SRC_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 {
@@ -383,6 +439,14 @@ class InOrderCPU : public BaseCPU
         }
     };
 
+  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. */
@@ -396,15 +460,13 @@ class InOrderCPU : public BaseCPU
     /** Initialize the CPU */
     void init();
 
-    /** Get a Memory Port */
-    Port* getPort(const std::string &if_name, int idx = 0);
-
-#if FULL_SYSTEM
     /** HW return from error interrupt. */
     Fault hwrei(ThreadID tid);
 
     bool simPalCheck(int palFunc, ThreadID tid);
 
+    void checkForInterrupts();
+
     /** Returns the Fault for any valid interrupt. */
     Fault getInterrupts();
 
@@ -414,51 +476,67 @@ class InOrderCPU : public BaseCPU
     /** Halts the CPU. */
     void halt() { panic("Halt not implemented!\n"); }
 
-    /** Update the Virt and Phys ports of all ThreadContexts to
-     * reflect change in memory connections. */
-    void updateMemPorts();
-
     /** Check if this address is a valid instruction address. */
     bool validInstAddr(Addr addr) { return true; }
 
     /** Check if this address is a valid data address. */
     bool validDataAddr(Addr addr) { return true; }
-#endif
 
-    /** trap() - sets up a trap event on the cpuTraps to handle given fault.
-     *  trapCPU() - Traps to handle given fault
-     */
-    void trap(Fault fault, ThreadID tid, DynInstPtr inst, int delay = 0);
-    void trapCPU(Fault fault, ThreadID tid, DynInstPtr inst);
+    /** Schedule a syscall on the CPU */
+    void syscallContext(Fault fault, ThreadID tid, DynInstPtr inst,
+                        Cycles delay = Cycles(0));
+
+    /** Executes a syscall.*/
+    void syscall(int64_t callnum, ThreadID tid);
+
+    /** Schedule a trap on the CPU */
+    void trapContext(Fault fault, ThreadID tid, DynInstPtr inst,
+                     Cycles delay = Cycles(0));
+
+    /** Perform trap to Handle Given Fault */
+    void trap(Fault fault, ThreadID tid, DynInstPtr inst);
+
+    /** Schedule thread activation on the CPU */
+    void activateContext(ThreadID tid, Cycles delay = Cycles(0));
 
     /** Add Thread to Active Threads List. */
-    void activateContext(ThreadID tid, int delay = 0);
     void activateThread(ThreadID tid);
+
+    /** Activate Thread In Each Pipeline Stage */
     void activateThreadInPipeline(ThreadID tid);
     
-    /** Add Thread to Active Threads List. */
-    void activateNextReadyContext(int delay = 0);
+    /** Schedule Thread Activation from Ready List */
+    void activateNextReadyContext(Cycles delay = Cycles(0));
+
+    /** Add Thread From Ready List to Active Threads List. */
     void activateNextReadyThread();
 
+    /** Schedule a thread deactivation on the CPU */
+    void deactivateContext(ThreadID tid, Cycles delay = Cycles(0));
+
     /** Remove from Active Thread List */
-    void deactivateContext(ThreadID tid, int delay = 0);
     void deactivateThread(ThreadID tid);
 
+    /** Schedule a thread suspension on the CPU */
+  void suspendContext(ThreadID tid);
+
     /** Suspend Thread, Remove from Active Threads List, Add to Suspend List */
-    void suspendContext(ThreadID tid, int delay = 0);
     void suspendThread(ThreadID tid);
 
+    /** 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 haltContext(ThreadID tid, int delay = 0);
     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 squashFromMemStall(DynInstPtr inst, ThreadID tid,
+                            Cycles delay = Cycles(0));
     void squashDueToMemStall(int stage_num, InstSeqNum seq_num, ThreadID tid);    
 
     void removePipelineStalls(ThreadID tid);
@@ -516,13 +594,17 @@ class InOrderCPU : public BaseCPU
 
     FloatRegBits readFloatRegBits(RegIndex reg_idx, ThreadID tid);
 
+    CCReg readCCReg(RegIndex reg_idx, ThreadID tid);
+
     void setIntReg(RegIndex reg_idx, uint64_t val, ThreadID tid);
 
     void setFloatReg(RegIndex reg_idx, FloatReg val, ThreadID tid);
 
     void setFloatRegBits(RegIndex reg_idx, FloatRegBits val,  ThreadID tid);
 
-    RegIndex flattenRegIdx(RegIndex reg_idx, ThreadID tid);
+    void setCCReg(RegIndex reg_idx, CCReg val, ThreadID tid);
+
+    RegIndex flattenRegIdx(RegIndex reg_idx, RegClass &reg_type, ThreadID tid);
 
     /** Reads a miscellaneous register. */
     MiscReg readMiscRegNoEffect(int misc_reg, ThreadID tid = 0);
@@ -574,22 +656,25 @@ class InOrderCPU : public BaseCPU
     /** 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, 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,ThreadID tid);
 
     /** Removes the instruction pointed to by the iterator. */
-    inline void squashInstIt(const ListIt &instIt, ThreadID tid);
+    inline void squashInstIt(const ListIt inst_it, ThreadID tid);
 
     /** Cleans up all instructions on the instruction remove list. */
     void cleanUpRemovedInsts();
@@ -612,9 +697,6 @@ class InOrderCPU : public BaseCPU
     Fault write(DynInstPtr inst, uint8_t *data, unsigned size,
                 Addr addr, unsigned flags, uint64_t *write_res = NULL);
 
-    /** Executes a syscall.*/
-    void syscall(int64_t callnum, ThreadID tid);
-
   public:
     /** Per-Thread List of all the instructions in flight. */
     std::list<DynInstPtr> instList[ThePipeline::MaxThreads];
@@ -624,6 +706,8 @@ class InOrderCPU : public BaseCPU
      */
     std::queue<ListIt> removeList;
 
+    bool trapPending[ThePipeline::MaxThreads];
+
     /** List of all the cpu event requests that will be removed at the end of
      *  the current cycle.
      */
@@ -706,11 +790,9 @@ class InOrderCPU : public BaseCPU
     /** Wakes the CPU, rescheduling the CPU if it's not already active. */
     void wakeCPU();
 
-#if FULL_SYSTEM
     virtual void wakeup();
-#endif
 
-    // LL/SC debug functionality
+    /* LL/SC debug functionality
     unsigned stCondFails;
 
     unsigned readStCondFailures() 
@@ -718,6 +800,7 @@ class InOrderCPU : public BaseCPU
 
     unsigned setStCondFailures(unsigned st_fails) 
     { return stCondFails = st_fails; }
+    */
 
     /** Returns a pointer to a thread context. */
     ThreadContext *tcBase(ThreadID tid = 0)
@@ -726,7 +809,7 @@ class InOrderCPU : public BaseCPU
     }
 
     /** Count the Total Instructions Committed in the CPU. */
-    virtual Counter totalInstructions() const
+    virtual Counter totalInsts() const
     {
         Counter total(0);
 
@@ -736,14 +819,20 @@ class InOrderCPU : public BaseCPU
         return total;
     }
 
-#if FULL_SYSTEM
+    /** 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;
 
-    /** Pointer to physical memory. */
-    PhysicalMemory *physmem;
-#endif
-
     /** The global sequence number counter. */
     InstSeqNum globalSeqNum[ThePipeline::MaxThreads];
 
@@ -755,20 +844,16 @@ class InOrderCPU : public BaseCPU
     unsigned resReqCount;
 #endif
 
-    /** Counter of how many stages have completed switching out. */
-    int switchCount;
-
-    /** Pointers to all of the threads in the CPU. */
-    std::vector<Thread *> thread;
+    Addr lockAddr;
 
-    /** Pointer to the icache interface. */
-    MemInterface *icacheInterface;
+    /** Temporary fix for the lock flag, works in the UP case. */
+    bool lockFlag;
 
-    /** Pointer to the dcache interface. */
-    MemInterface *dcacheInterface;
+    /** Counter of how many stages have completed draining */
+    int drainCount;
 
-    /** Whether or not the CPU should defer its registration. */
-    bool deferRegistration;
+    /** Pointers to all of the threads in the CPU. */
+    std::vector<Thread *> thread;
 
     /** Per-Stage Instruction Tracing */
     bool stageTracing;
@@ -816,6 +901,9 @@ class InOrderCPU : public BaseCPU
     /** 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;