cpu: implement a bi-mode branch predictor
[gem5.git] / src / cpu / base.hh
index 6552be0d6db49dc48e6e4aa06ba71f944f218295..cc3f861cca93583fd66f19d7f82597204bff1b52 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 ARM Limited
+ * Copyright (c) 2011-2013 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
 
 #include <vector>
 
+// Before we do anything else, check if this build is the NULL ISA,
+// and if so stop here
+#include "config/the_isa.hh"
+#if THE_ISA == NULL_ISA
+#include "arch/null/cpu_dummy.hh"
+#else
 #include "arch/interrupts.hh"
 #include "arch/isa_traits.hh"
 #include "arch/microcode_rom.hh"
 #include "base/statistics.hh"
-#include "config/the_isa.hh"
 #include "mem/mem_object.hh"
 #include "sim/eventq.hh"
 #include "sim/full_system.hh"
 #include "sim/insttracer.hh"
+#include "sim/system.hh"
 
 struct BaseCPUParams;
-class BranchPred;
 class CheckerCPU;
 class ThreadContext;
-class System;
 
 class CPUProgressEvent : public Event
 {
@@ -97,6 +101,13 @@ class BaseCPU : public MemObject
     // therefore no setCpuId() method is provided
     int _cpuId;
 
+    /** Each cpu will have a socket ID that corresponds to its physical location
+     * in the system. This is usually used to bucket cpu cores under single DVFS
+     * domain. This information may also be required by the OS to identify the
+     * cpu core grouping (as in the case of ARM via MPIDR register)
+     */
+    const uint32_t _socketId;
+
     /** instruction side request id that must be placed in all requests */
     MasterID _instMasterId;
 
@@ -114,37 +125,11 @@ class BaseCPU : public MemObject
      * used to generate a taskId */
     uint32_t _pid;
 
-    /**
-     * Define a base class for the CPU ports (instruction and data)
-     * that is refined in the subclasses. This class handles the
-     * common cases, i.e. the functional accesses and the status
-     * changes and address range queries. The default behaviour for
-     * both atomic and timing access is to panic and the corresponding
-     * subclasses have to override these methods.
-     */
-    class CpuPort : public MasterPort
-    {
-      public:
-
-        /**
-         * Create a CPU port with a name and a structural owner.
-         *
-         * @param _name port name including the owner
-         * @param _name structural owner of this port
-         */
-        CpuPort(const std::string& _name, MemObject* _owner) :
-            MasterPort(_name, _owner)
-        { }
-
-      protected:
-
-        virtual bool recvTimingResp(PacketPtr pkt);
+    /** Is the CPU switched out or active? */
+    bool _switchedOut;
 
-        virtual void recvRetry();
-
-        virtual void recvFunctionalSnoop(PacketPtr pkt);
-
-    };
+    /** Cache the cache line size that we get from the system */
+    const unsigned int _cacheLineSize;
 
   public:
 
@@ -154,7 +139,7 @@ class BaseCPU : public MemObject
      *
      * @return a reference to the data port
      */
-    virtual CpuPort &getDataPort() = 0;
+    virtual MasterPort &getDataPort() = 0;
 
     /**
      * Purely virtual method that returns a reference to the instruction
@@ -162,10 +147,13 @@ class BaseCPU : public MemObject
      *
      * @return a reference to the instruction port
      */
-    virtual CpuPort &getInstPort() = 0;
+    virtual MasterPort &getInstPort() = 0;
 
     /** Reads this CPU's ID. */
-    int cpuId() { return _cpuId; }
+    int cpuId() const { return _cpuId; }
+
+    /** Reads this CPU's Socket ID. */
+    uint32_t socketId() const { return _socketId; }
 
     /** Reads this CPU's unique data requestor ID */
     MasterID dataMasterId() { return _dataMasterId; }
@@ -281,7 +269,10 @@ class BaseCPU : public MemObject
    int findContext(ThreadContext *tc);
 
    /// Given a thread num get tho thread context for it
-   ThreadContext *getContext(int tn) { return threadContexts[tn]; }
+   virtual ThreadContext *getContext(int tn) { return threadContexts[tn]; }
+
+   /// Get the number of thread contexts available
+   unsigned numContexts() { return threadContexts.size(); }
 
   public:
     typedef BaseCPUParams Params;
@@ -320,6 +311,35 @@ class BaseCPU : public MemObject
      */
     virtual void takeOverFrom(BaseCPU *cpu);
 
+    /**
+     * Flush all TLBs in the CPU.
+     *
+     * This method is mainly used to flush stale translations when
+     * switching CPUs. It is also exported to the Python world to
+     * allow it to request a TLB flush after draining the CPU to make
+     * it easier to compare traces when debugging
+     * handover/checkpointing.
+     */
+    void flushTLBs();
+
+    /**
+     * Determine if the CPU is switched out.
+     *
+     * @return True if the CPU is switched out, false otherwise.
+     */
+    bool switchedOut() const { return _switchedOut; }
+
+    /**
+     * Verify that the system is in a memory mode supported by the
+     * CPU.
+     *
+     * Implementations are expected to query the system for the
+     * current memory mode and ensure that it is what the CPU model
+     * expects. If the check fails, the implementation should
+     * terminate the simulation using fatal().
+     */
+    virtual void verifyMemoryMode() const { };
+
     /**
      *  Number of threads we're actually simulating (<= SMT_MAX_THREADS).
      * This is a constant for the duration of the simulation.
@@ -342,29 +362,88 @@ class BaseCPU : public MemObject
 
     System *system;
 
+    /**
+     * Get the cache line size of the system.
+     */
+    inline unsigned int cacheLineSize() const { return _cacheLineSize; }
+
     /**
      * Serialize this object to the given output stream.
+     *
+     * @note CPU models should normally overload the serializeThread()
+     * method instead of the serialize() method as this provides a
+     * uniform data format for all CPU models and promotes better code
+     * reuse.
+     *
      * @param os The stream to serialize to.
      */
     virtual void serialize(std::ostream &os);
 
     /**
      * Reconstruct the state of this object from a checkpoint.
+     *
+     * @note CPU models should normally overload the
+     * unserializeThread() method instead of the unserialize() method
+     * as this provides a uniform data format for all CPU models and
+     * promotes better code reuse.
+
      * @param cp The checkpoint use.
-     * @param section The section name of this object
+     * @param section The section name of this object.
      */
     virtual void unserialize(Checkpoint *cp, const std::string &section);
 
     /**
-     * Return pointer to CPU's branch predictor (NULL if none).
-     * @return Branch predictor pointer.
+     * Serialize a single thread.
+     *
+     * @param os The stream to serialize to.
+     * @param tid ID of the current thread.
      */
-    virtual BranchPred *getBranchPred() { return NULL; };
+    virtual void serializeThread(std::ostream &os, ThreadID tid) {};
+
+    /**
+     * Unserialize one thread.
+     *
+     * @param cp The checkpoint use.
+     * @param section The section name of this thread.
+     * @param tid ID of the current thread.
+     */
+    virtual void unserializeThread(Checkpoint *cp, const std::string &section,
+                                   ThreadID tid) {};
 
     virtual Counter totalInsts() const = 0;
 
     virtual Counter totalOps() const = 0;
 
+    /**
+     * Schedule an event that exits the simulation loops after a
+     * predefined number of instructions.
+     *
+     * This method is usually called from the configuration script to
+     * get an exit event some time in the future. It is typically used
+     * when the script wants to simulate for a specific number of
+     * instructions rather than ticks.
+     *
+     * @param tid Thread monitor.
+     * @param insts Number of instructions into the future.
+     * @param cause Cause to signal in the exit event.
+     */
+    void scheduleInstStop(ThreadID tid, Counter insts, const char *cause);
+
+    /**
+     * Schedule an event that exits the simulation loops after a
+     * predefined number of load operations.
+     *
+     * This method is usually called from the configuration script to
+     * get an exit event some time in the future. It is typically used
+     * when the script wants to simulate for a specific number of
+     * loads rather than ticks.
+     *
+     * @param tid Thread monitor.
+     * @param loads Number of load instructions into the future.
+     * @param cause Cause to signal in the exit event.
+     */
+    void scheduleLoadStop(ThreadID tid, Counter loads, const char *cause);
+
     // Function tracing
   private:
     bool functionTracingEnabled;
@@ -415,4 +494,6 @@ class BaseCPU : public MemObject
     Stats::Scalar numWorkItemsCompleted;
 };
 
+#endif // THE_ISA == NULL_ISA
+
 #endif // __CPU_BASE_HH__