pwr: Adds logic to enter power gating for the cpu model
[gem5.git] / src / cpu / simple / atomic.hh
index f68f41a90d5e3d0ae8918d56cb3c574cdd77837d..c9dd954bb098c669f955c063376ae7b90ddbf9fa 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012-2013,2015 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.
  *
 #define __CPU_SIMPLE_ATOMIC_HH__
 
 #include "cpu/simple/base.hh"
+#include "cpu/simple/exec_context.hh"
+#include "mem/request.hh"
+#include "params/AtomicSimpleCPU.hh"
+#include "sim/probe/probe.hh"
 
 class AtomicSimpleCPU : public BaseSimpleCPU
 {
   public:
 
-    struct Params : public BaseSimpleCPU::Params {
-        int width;
-        bool simulate_stalls;
-    };
-
-    AtomicSimpleCPU(Params *params);
+    AtomicSimpleCPU(AtomicSimpleCPUParams *params);
     virtual ~AtomicSimpleCPU();
 
-    virtual void init();
-
-  public:
-    //
-    enum Status {
-        Running,
-        Idle,
-        SwitchedOut
-    };
-
-  protected:
-    Status _status;
-
-    Status status() const { return _status; }
+    void init() override;
 
   private:
 
-    struct TickEvent : public Event
-    {
-        AtomicSimpleCPU *cpu;
-
-        TickEvent(AtomicSimpleCPU *c);
-        void process();
-        const char *description();
-    };
-
-    TickEvent tickEvent;
+    EventFunctionWrapper tickEvent;
 
     const int width;
-    const bool simulate_stalls;
+    bool locked;
+    const bool simulate_data_stalls;
+    const bool simulate_inst_stalls;
 
     // main simulation loop (one cycle)
     void tick();
 
-    class CpuPort : public Port
+    /**
+     * Check if a system is in a drained state.
+     *
+     * We need to drain if:
+     * <ul>
+     * <li>We are in the middle of a microcode sequence as some CPUs
+     *     (e.g., HW accelerated CPUs) can't be started in the middle
+     *     of a gem5 microcode sequence.
+     *
+     * <li>The CPU is in a LLSC region. This shouldn't normally happen
+     *     as these are executed atomically within a single tick()
+     *     call. The only way this can happen at the moment is if
+     *     there is an event in the PC event queue that affects the
+     *     CPU state while it is in an LLSC region.
+     *
+     * <li>Stay at PC is true.
+     * </ul>
+     */
+    bool isDrained() {
+        SimpleExecContext &t_info = *threadInfo[curThread];
+
+        return t_info.thread->microPC() == 0 &&
+            !locked &&
+            !t_info.stayAtPC;
+    }
+
+    /**
+     * Try to complete a drain request.
+     *
+     * @returns true if the CPU is drained, false otherwise.
+     */
+    bool tryCompleteDrain();
+
+    /**
+     * An AtomicCPUPort overrides the default behaviour of the
+     * recvAtomicSnoop and ignores the packet instead of panicking. It
+     * also provides an implementation for the purely virtual timing
+     * functions and panics on either of these.
+     */
+    class AtomicCPUPort : public MasterPort
     {
+
       public:
 
-        CpuPort(const std::string &_name, AtomicSimpleCPU *_cpu)
-            : Port(_name, _cpu), cpu(_cpu)
+        AtomicCPUPort(const std::string &_name, BaseSimpleCPU* _cpu)
+            : MasterPort(_name, _cpu)
         { }
 
-        bool snoopRangeSent;
-
       protected:
 
-        AtomicSimpleCPU *cpu;
+        bool recvTimingResp(PacketPtr pkt)
+        {
+            panic("Atomic CPU doesn't expect recvTimingResp!\n");
+            return true;
+        }
 
-        virtual bool recvTiming(PacketPtr pkt);
+        void recvReqRetry()
+        {
+            panic("Atomic CPU doesn't expect recvRetry!\n");
+        }
 
-        virtual Tick recvAtomic(PacketPtr pkt);
+    };
+
+    class AtomicCPUDPort : public AtomicCPUPort
+    {
 
-        virtual void recvFunctional(PacketPtr pkt);
+      public:
 
-        virtual void recvStatusChange(Status status);
+        AtomicCPUDPort(const std::string &_name, BaseSimpleCPU* _cpu)
+            : AtomicCPUPort(_name, _cpu), cpu(_cpu)
+        {
+            cacheBlockMask = ~(cpu->cacheLineSize() - 1);
+        }
 
-        virtual void recvRetry();
+        bool isSnooping() const { return true; }
 
-        virtual void getDeviceAddressRanges(AddrRangeList &resp,
-            bool &snoop)
-        { resp.clear(); snoop = true; }
+        Addr cacheBlockMask;
+      protected:
+        BaseSimpleCPU *cpu;
 
+        virtual Tick recvAtomicSnoop(PacketPtr pkt);
+        virtual void recvFunctionalSnoop(PacketPtr pkt);
     };
-    CpuPort icachePort;
 
-    class DcachePort : public CpuPort
-    {
-      public:
-        DcachePort(const std::string &_name, AtomicSimpleCPU *_cpu)
-            : CpuPort(_name, _cpu)
-        { }
 
-        virtual void setPeer(Port *port);
-    };
-    DcachePort dcachePort;
+    AtomicCPUPort icachePort;
+    AtomicCPUDPort dcachePort;
 
-    CpuPort physmemPort;
-    bool hasPhysMemPort;
+    bool fastmem;
     Request ifetch_req;
     Request data_read_req;
     Request data_write_req;
@@ -130,32 +166,49 @@ class AtomicSimpleCPU : public BaseSimpleCPU
     bool dcache_access;
     Tick dcache_latency;
 
-    Range<Addr> physMemAddr;
+    /** Probe Points. */
+    ProbePointArg<std::pair<SimpleThread*, const StaticInstPtr>> *ppCommit;
+
+  protected:
+
+    /** Return a reference to the data port. */
+    MasterPort &getDataPort() override { return dcachePort; }
+
+    /** Return a reference to the instruction port. */
+    MasterPort &getInstPort() override { return icachePort; }
+
+    /** Perform snoop for other cpu-local thread contexts. */
+    void threadSnoop(PacketPtr pkt, ThreadID sender);
 
   public:
 
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    DrainState drain() override;
+    void drainResume() override;
+
+    void switchOut() override;
+    void takeOverFrom(BaseCPU *oldCPU) override;
+
+    void verifyMemoryMode() const override;
 
-    virtual void serialize(std::ostream &os);
-    virtual void unserialize(Checkpoint *cp, const std::string &section);
-    virtual void resume();
+    void activateContext(ThreadID thread_num) override;
+    void suspendContext(ThreadID thread_num) override;
 
-    void switchOut();
-    void takeOverFrom(BaseCPU *oldCPU);
+    Fault readMem(Addr addr, uint8_t *data, unsigned size,
+                  Request::Flags flags) override;
 
-    virtual void activateContext(int thread_num, int delay);
-    virtual void suspendContext(int thread_num);
+    Fault initiateMemRead(Addr addr, unsigned size,
+                          Request::Flags flags) override;
 
-    template <class T>
-    Fault read(Addr addr, T &data, unsigned flags);
+    Fault writeMem(uint8_t *data, unsigned size,
+                   Addr addr, Request::Flags flags, uint64_t *res) override;
 
-    template <class T>
-    Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
+    void regProbePoints() override;
 
-    Fault translateDataReadAddr(Addr vaddr, Addr &paddr,
-            int size, unsigned flags);
-    Fault translateDataWriteAddr(Addr vaddr, Addr &paddr,
-            int size, unsigned flags);
+    /**
+     * Print state of address in memory system via PrintReq (for
+     * debugging).
+     */
+    void printAddr(Addr a);
 };
 
 #endif // __CPU_SIMPLE_ATOMIC_HH__