Automated merge with ssh://repo.gem5.org/gem5
[gem5.git] / src / sim / system.hh
index 7e21bd5872d6b108f9e0299e737cad369e514031..44383c399342e6f0f2b6fdf40004e7c742515415 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * Copyright (c) 2011 Regents of the University of California
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Steve Reinhardt
+ *          Lisa Hsu
+ *          Nathan Binkert
+ *          Rick Strong
  */
 
 #ifndef __SYSTEM_HH__
 #include "base/loader/symtab.hh"
 #include "base/misc.hh"
 #include "base/statistics.hh"
+#include "config/full_system.hh"
 #include "cpu/pc_event.hh"
+#include "enums/MemoryMode.hh"
 #include "mem/port.hh"
+#include "params/System.hh"
 #include "sim/sim_object.hh"
+
 #if FULL_SYSTEM
 #include "kern/system_events.hh"
-#include "mem/vport.hh"
 #endif
 
 class BaseCPU;
-class ExecContext;
+class ThreadContext;
 class ObjectFile;
 class PhysicalMemory;
 
 #if FULL_SYSTEM
 class Platform;
-class GDBListener;
-class RemoteGDB;
-namespace Kernel { class Binning; }
+class FunctionalPort;
+class VirtualPort;
 #endif
+class GDBListener;
+class BaseRemoteGDB;
 
 class System : public SimObject
 {
   public:
+
+    static const char *MemoryModeStrings[3];
+
+    Enums::MemoryMode
+    getMemoryMode()
+    {
+        assert(memoryMode);
+        return memoryMode;
+    }
+
+    /** Change the memory mode of the system. This should only be called by the
+     * python!!
+     * @param mode Mode to change to (atomic/timing)
+     */
+    void setMemoryMode(Enums::MemoryMode mode);
+
     PhysicalMemory *physmem;
     PCEventQueue pcEventQueue;
 
-    std::vector<ExecContext *> execContexts;
-    int numcpus;
+    std::vector<ThreadContext *> threadContexts;
+    int _numContexts;
 
-    int getNumCPUs()
+    ThreadContext *getThreadContext(ThreadID tid)
     {
-        if (numcpus != execContexts.size())
-            panic("cpu array not fully populated!");
+        return threadContexts[tid];
+    }
 
-        return numcpus;
+    int numContexts()
+    {
+        assert(_numContexts == (int)threadContexts.size());
+        return _numContexts;
     }
 
+    /** Return number of running (non-halted) thread contexts in
+     * system.  These threads could be Active or Suspended. */
+    int numRunningContexts();
+
+    /** List to store ranges of memories in this system */
+    AddrRangeList memRanges;
+
+    /** check if an address points to valid system memory
+     * and thus we can fetch instructions out of it
+     */
+    bool isMemory(const Addr addr) const;
+
 #if FULL_SYSTEM
     Platform *platform;
     uint64_t init_param;
 
     /** Port to physical memory used for writing object files into ram at
      * boot.*/
-    FunctionalPort functionalPort;
-    VirtualPort virtPort;
+    FunctionalPort *functionalPort;
+    VirtualPort *virtPort;
 
     /** kernel symbol table */
     SymbolTable *kernelSymtab;
@@ -96,16 +137,90 @@ class System : public SimObject
     /** Entry point in the kernel to start at */
     Addr kernelEntry;
 
-    Kernel::Binning *kernelBinning;
+    /** Mask that should be anded for binary/symbol loading.
+     * This allows one two different OS requirements for the same ISA to be
+     * handled.  Some OSes are compiled for a virtual address and need to be
+     * loaded into physical memory that starts at address 0, while other
+     * bare metal tools generate images that start at address 0.
+     */
+    Addr loadAddrMask;
 
 #else
 
-    int page_ptr;
+    Addr pagePtr;
+
+  protected:
+    uint64_t nextPID;
+
+  public:
+    uint64_t allocatePID()
+    {
+        return nextPID++;
+    }
+
+    /** Amount of physical memory that is still free */
+    Addr freeMemSize();
+
+    /** Amount of physical memory that exists */
+    Addr memSize();
 
 
 #endif // FULL_SYSTEM
 
   protected:
+    Enums::MemoryMode memoryMode;
+    uint64_t workItemsBegin;
+    uint64_t workItemsEnd;
+    uint32_t numWorkIds;
+    std::vector<bool> activeCpus;
+
+  public:
+    virtual void regStats();
+    /**
+     * Called by pseudo_inst to track the number of work items started by this
+     * system.
+     */
+    uint64_t
+    incWorkItemsBegin()
+    {
+        return ++workItemsBegin;
+    }
+
+    /**
+     * Called by pseudo_inst to track the number of work items completed by
+     * this system.
+     */
+    uint64_t 
+    incWorkItemsEnd()
+    {
+        return ++workItemsEnd;
+    }
+
+    /**
+     * Called by pseudo_inst to mark the cpus actively executing work items.
+     * Returns the total number of cpus that have executed work item begin or
+     * ends.
+     */
+    int 
+    markWorkItem(int index)
+    {
+        int count = 0;
+        assert(index < activeCpus.size());
+        activeCpus[index] = true;
+        for (std::vector<bool>::iterator i = activeCpus.begin(); 
+             i < activeCpus.end(); i++) {
+            if (*i) count++;
+        }
+        return count;
+    }
+
+    inline void workItemBegin(uint32_t tid, uint32_t workid)
+    {
+        std::pair<uint32_t,uint32_t> p(tid, workid);
+        lastWorkItemStarted[p] = curTick();
+    }
+
+    void workItemEnd(uint32_t tid, uint32_t workid);
 
 #if FULL_SYSTEM
     /**
@@ -120,7 +235,7 @@ class System : public SimObject
      * up in the specified symbol table.
      */
     template <class T>
-    T *System::addFuncEvent(SymbolTable *symtab, const char *lbl)
+    T *addFuncEvent(SymbolTable *symtab, const char *lbl)
     {
         Addr addr = 0; // initialize only to avoid compiler warning
 
@@ -134,37 +249,19 @@ class System : public SimObject
 
     /** Add a function-based event to kernel code. */
     template <class T>
-    T *System::addKernelFuncEvent(const char *lbl)
+    T *addKernelFuncEvent(const char *lbl)
     {
         return addFuncEvent<T>(kernelSymtab, lbl);
     }
 
 #endif
   public:
-#if FULL_SYSTEM
-    std::vector<RemoteGDB *> remoteGDB;
+    std::vector<BaseRemoteGDB *> remoteGDB;
     std::vector<GDBListener *> gdbListen;
-    virtual bool breakpoint() = 0;
-#endif // FULL_SYSTEM
+    bool breakpoint();
 
   public:
-    struct Params
-    {
-        std::string name;
-        PhysicalMemory *physmem;
-
-#if FULL_SYSTEM
-        Tick boot_cpu_frequency;
-        std::string boot_osflags;
-        uint64_t init_param;
-        bool bin;
-        std::vector<std::string> binned_fns;
-        bool bin_int;
-
-        std::string kernel_path;
-        std::string readfile;
-#endif
-    };
+    typedef SystemParams Params;
 
   protected:
     Params *_params;
@@ -173,7 +270,7 @@ class System : public SimObject
     System(Params *p);
     ~System();
 
-    void startup();
+    void initState();
 
     const Params *params() const { return (const Params *)_params; }
 
@@ -200,18 +297,25 @@ class System : public SimObject
 
 #else
 
-    Addr new_page();
+    /// Allocate npages contiguous unused physical pages
+    /// @return Starting address of first page
+    Addr allocPhysPages(int npages);
 
 #endif // FULL_SYSTEM
 
-    int registerExecContext(ExecContext *xc, int xcIndex);
-    void replaceExecContext(ExecContext *xc, int xcIndex);
+    int registerThreadContext(ThreadContext *tc, int assigned=-1);
+    void replaceThreadContext(ThreadContext *tc, int context_id);
 
-    void regStats();
     void serialize(std::ostream &os);
     void unserialize(Checkpoint *cp, const std::string &section);
+    virtual void resume();
 
   public:
+    Counter totalNumInsts;
+    EventQueue instEventQueue;
+    std::map<std::pair<uint32_t,uint32_t>, Tick>  lastWorkItemStarted;
+    std::map<uint32_t, Stats::Histogram*> workItemStats;
+
     ////////////////////////////////////////////
     //
     // STATIC GLOBAL SYSTEM LIST