ruby: cleaned up ruby profilers
authorBrad Beckmann <Brad.Beckmann@amd.com>
Sat, 30 Jan 2010 04:29:22 +0000 (20:29 -0800)
committerBrad Beckmann <Brad.Beckmann@amd.com>
Sat, 30 Jan 2010 04:29:22 +0000 (20:29 -0800)
Cleaned up the ruby profilers by moving the memory controller profiling code
out of the main profiler object and into a separate object similar to the
current CacheProfiler.  Both the CacheProfiler and MemCntrlProfiler are
specific to a particular Ruby object, CacheMemory and MemoryControl
respectively.  Therefore, these profilers should not be SimObjects and
created by the python configuration system, but instead private objects.  This
simplifies the creation of these profilers.

14 files changed:
configs/ruby/MOESI_hammer.py
configs/ruby/Ruby.py
src/mem/ruby/profiler/CacheProfiler.cc
src/mem/ruby/profiler/CacheProfiler.hh
src/mem/ruby/profiler/MemCntrlProfiler.cc [new file with mode: 0644]
src/mem/ruby/profiler/MemCntrlProfiler.hh [new file with mode: 0644]
src/mem/ruby/profiler/Profiler.cc
src/mem/ruby/profiler/Profiler.hh
src/mem/ruby/profiler/Profiler.py
src/mem/ruby/profiler/SConscript
src/mem/ruby/system/Cache.py
src/mem/ruby/system/CacheMemory.cc
src/mem/ruby/system/MemoryControl.cc
src/mem/ruby/system/MemoryControl.hh

index f35ab20c47e45d638fc0dc49e0c8d15cab7d2adb..5273f597bff82f6347e38e9dcb93cc62ce0d4b4e 100644 (file)
@@ -74,14 +74,9 @@ def create_system(options, phys_mem, piobus, dma_devices):
         #
         # First create the Ruby objects associated with this cpu
         #
-        l1i_profiler = CacheProfiler(description = ("l1i_%s_profiler" % i))
-        l1i_cache = L1Cache(cache_profiler = l1i_profiler)
-
-        l1d_profiler = CacheProfiler(description = ("l1d_%s_profiler" % i))
-        l1d_cache = L1Cache(cache_profiler = l1d_profiler)
-
-        l2_profiler = CacheProfiler(description = ("l2_%s_profiler" % i))
-        l2_cache = L2Cache(cache_profiler = l2_profiler)
+        l1i_cache = L1Cache()
+        l1d_cache = L1Cache()
+        l2_cache = L2Cache()
 
         cpu_seq = RubySequencer(icache = l1i_cache,
                                 dcache = l1d_cache,
index 37c43602d8c35e0593e6fbf0b4d4d84040e44dde..abc9a8df51e29a4d91d6e468e4b51daeb140a1fc 100644 (file)
@@ -57,20 +57,7 @@ def create_system(options, physmem, piobus = None, dma_devices = []):
     mem_size_mb = sum([int(dir_cntrl.directory.size_mb) \
                        for dir_cntrl in dir_cntrls])
 
-    #
-    # determine the number of memory controllers and other memory controller
-    # parameters for the profiler
-    #
-    mcCount = len(dir_cntrls)
-    banksPerRank = dir_cntrls[0].memBuffer.banks_per_rank
-    ranksPerDimm = dir_cntrls[0].memBuffer.ranks_per_dimm
-    dimmsPerChannel = dir_cntrls[0].memBuffer.dimms_per_channel
-
-    ruby_profiler = RubyProfiler(num_of_sequencers = len(cpu_sequencers),
-                                 mem_cntrl_count = mcCount,
-                                 banks_per_rank = banksPerRank,
-                                 ranks_per_dimm = ranksPerDimm,
-                                 dimms_per_channel = dimmsPerChannel)
+    ruby_profiler = RubyProfiler(num_of_sequencers = len(cpu_sequencers))
     
     ruby = RubySystem(clock = options.clock,
                       network = network,
index a01d68050714c572281c427453ba42b4051dd279..4745067345b04298ae8daefb494d1bf05ce27c36 100644 (file)
 #include "mem/ruby/profiler/Profiler.hh"
 #include "mem/gems_common/Vector.hh"
 
-CacheProfiler::CacheProfiler(const CacheProfilerParams* params)
-  : SimObject(params), m_requestSize(-1)
+CacheProfiler::CacheProfiler(const string& description)
 {
-  m_description = params->description;
+  m_description = description;
   m_requestTypeVec_ptr = new Vector<int>;
   m_requestTypeVec_ptr->setSize(int(CacheRequestType_NUM));
 
@@ -60,7 +59,7 @@ CacheProfiler::~CacheProfiler()
 
 void CacheProfiler::printStats(ostream& out) const
 {
-  out << m_description << " cache stats: " << endl;
+  out << "Cache Stats: " << m_description << endl;
   string description = "  " + m_description;
 
   out << description << "_total_misses: " << m_misses << endl;
@@ -140,9 +139,3 @@ void CacheProfiler::addStatSample(CacheRequestType requestType, AccessModeType t
     m_hw_prefetches++;
   }
 }
-
-CacheProfiler *
-CacheProfilerParams::create()
-{
-    return new CacheProfiler(this);
-}
index eeed1153bd8b1cf1ff603df4e18ca3fe5e9d0e5a..6c5fbb9884bce625d27a0df9af2236076f99d8a9 100644 (file)
 #include "mem/protocol/PrefetchBit.hh"
 #include "mem/protocol/CacheRequestType.hh"
 
-#include "params/CacheProfiler.hh"
-
 template <class TYPE> class Vector;
 
-class CacheProfiler : public SimObject {
+class CacheProfiler {
 public:
   // Constructors
-  typedef CacheProfilerParams Params;
-  CacheProfiler(const Params *);
+  CacheProfiler(const string& description);
 
   // Destructor
   ~CacheProfiler();
diff --git a/src/mem/ruby/profiler/MemCntrlProfiler.cc b/src/mem/ruby/profiler/MemCntrlProfiler.cc
new file mode 100644 (file)
index 0000000..693d43d
--- /dev/null
@@ -0,0 +1,184 @@
+
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * 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.
+ */
+
+#include "mem/ruby/profiler/MemCntrlProfiler.hh"
+
+MemCntrlProfiler::MemCntrlProfiler(const string& description,
+                                   int banks_per_rank,
+                                   int ranks_per_dimm,
+                                   int dimms_per_channel)
+{
+    m_description = description;
+    m_banks_per_rank = banks_per_rank;
+    m_ranks_per_dimm = ranks_per_dimm;
+    m_dimms_per_channel = dimms_per_channel;
+
+    int totalBanks = banks_per_rank * 
+                     ranks_per_dimm * 
+                     dimms_per_channel;
+
+    m_memBankCount.setSize(totalBanks);
+
+    clearStats();
+}
+
+MemCntrlProfiler::~MemCntrlProfiler()
+{
+}
+
+void MemCntrlProfiler::printStats(ostream& out) const
+{
+    if (m_memReq || m_memRefresh) {    // if there's a memory controller at all
+        uint64 total_stalls = m_memInputQ + m_memBankQ + m_memWaitCycles;
+        double stallsPerReq = total_stalls * 1.0 / m_memReq;
+        out << "Memory controller: " << m_description << ":" << endl;
+        out << "  memory_total_requests: " << m_memReq << endl;  // does not include refreshes
+        out << "  memory_reads: " << m_memRead << endl;
+        out << "  memory_writes: " << m_memWrite << endl;
+        out << "  memory_refreshes: " << m_memRefresh << endl;
+        out << "  memory_total_request_delays: " << total_stalls << endl;
+        out << "  memory_delays_per_request: " << stallsPerReq << endl;
+        out << "  memory_delays_in_input_queue: " << m_memInputQ << endl;
+        out << "  memory_delays_behind_head_of_bank_queue: " << m_memBankQ << endl;
+        out << "  memory_delays_stalled_at_head_of_bank_queue: " << m_memWaitCycles << endl;
+        // Note:  The following "memory stalls" entries are a breakdown of the
+        // cycles which already showed up in m_memWaitCycles.  The order is
+        // significant; it is the priority of attributing the cycles.
+        // For example, bank_busy is before arbitration because if the bank was
+        // busy, we didn't even check arbitration.
+        // Note:  "not old enough" means that since we grouped waiting heads-of-queues
+        // into batches to avoid starvation, a request in a newer batch
+        // didn't try to arbitrate yet because there are older requests waiting.
+        out << "  memory_stalls_for_bank_busy: " << m_memBankBusy << endl;
+        out << "  memory_stalls_for_random_busy: " << m_memRandBusy << endl;
+        out << "  memory_stalls_for_anti_starvation: " << m_memNotOld << endl;
+        out << "  memory_stalls_for_arbitration: " << m_memArbWait << endl;
+        out << "  memory_stalls_for_bus: " << m_memBusBusy << endl;
+        out << "  memory_stalls_for_tfaw: " << m_memTfawBusy << endl;
+        out << "  memory_stalls_for_read_write_turnaround: " << m_memReadWriteBusy << endl;
+        out << "  memory_stalls_for_read_read_turnaround: " << m_memDataBusBusy << endl;
+        out << "  accesses_per_bank: ";
+        for (int bank=0; bank < m_memBankCount.size(); bank++) {
+            out << m_memBankCount[bank] << "  ";
+        }
+    }  else {
+        out << "Memory Controller: " << m_description
+            << " no stats recorded." << endl;
+    }    
+    out << endl;
+    out << endl;
+}
+
+void MemCntrlProfiler::clearStats()
+{
+    m_memReq = 0;
+    m_memBankBusy = 0;
+    m_memBusBusy = 0;
+    m_memTfawBusy = 0;
+    m_memReadWriteBusy = 0;
+    m_memDataBusBusy = 0;
+    m_memRefresh = 0;
+    m_memRead = 0;
+    m_memWrite = 0;
+    m_memWaitCycles = 0;
+    m_memInputQ = 0;
+    m_memBankQ = 0;
+    m_memArbWait = 0;
+    m_memRandBusy = 0;
+    m_memNotOld = 0;
+
+    for (int bank=0; 
+         bank < m_memBankCount.size(); 
+         bank++) {
+        m_memBankCount[bank] = 0;
+    }
+}
+
+void MemCntrlProfiler::profileMemReq(int bank) {
+  m_memReq++;
+  m_memBankCount[bank]++;
+}
+
+void MemCntrlProfiler::profileMemBankBusy() {    
+  m_memBankBusy++; 
+}
+
+void MemCntrlProfiler::profileMemBusBusy() {    
+  m_memBusBusy++; 
+}
+
+void MemCntrlProfiler::profileMemReadWriteBusy() {    
+  m_memReadWriteBusy++; 
+}
+
+void MemCntrlProfiler::profileMemDataBusBusy() {    
+  m_memDataBusBusy++; 
+}
+
+void MemCntrlProfiler::profileMemTfawBusy() {    
+  m_memTfawBusy++; 
+}
+
+void MemCntrlProfiler::profileMemRefresh() {    
+  m_memRefresh++; 
+}
+
+void MemCntrlProfiler::profileMemRead() {    
+  m_memRead++; 
+}
+
+void MemCntrlProfiler::profileMemWrite() {    
+  m_memWrite++; 
+}
+
+void MemCntrlProfiler::profileMemWaitCycles(int cycles) {
+  m_memWaitCycles += cycles; 
+}
+
+void MemCntrlProfiler::profileMemInputQ(int cycles) {    
+  m_memInputQ += cycles; 
+}
+
+void MemCntrlProfiler::profileMemBankQ(int cycles) {    
+  m_memBankQ += cycles; 
+}
+
+void MemCntrlProfiler::profileMemArbWait(int cycles) {    
+  m_memArbWait += cycles; 
+}
+
+void MemCntrlProfiler::profileMemRandBusy() {    
+  m_memRandBusy++; 
+}
+
+void MemCntrlProfiler::profileMemNotOld() {    
+  m_memNotOld++; 
+}
+
+
diff --git a/src/mem/ruby/profiler/MemCntrlProfiler.hh b/src/mem/ruby/profiler/MemCntrlProfiler.hh
new file mode 100644 (file)
index 0000000..5343fac
--- /dev/null
@@ -0,0 +1,123 @@
+
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * 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.
+ */
+
+/*
+ * MemCntrlProfiler.hh
+ *
+ * Description:
+ *
+ * $Id$
+ *
+ */
+
+#ifndef MEM_CNTRL_PROFILER_H
+#define MEM_CNTRL_PROFILER_H
+
+#include "mem/gems_common/Vector.hh"
+#include "mem/ruby/common/Global.hh"
+
+template <class TYPE> class Vector;
+
+class MemCntrlProfiler {
+public:
+  // Constructors
+  MemCntrlProfiler(const string& description,
+                   int banks_per_rank,
+                   int ranks_per_dimm,
+                   int dimms_per_channel);
+
+  // Destructor
+  ~MemCntrlProfiler();
+
+  // Public Methods
+  void printStats(ostream& out) const;
+  void clearStats();
+
+  void profileMemReq(int bank);
+  void profileMemBankBusy();
+  void profileMemBusBusy();
+  void profileMemTfawBusy();
+  void profileMemReadWriteBusy();
+  void profileMemDataBusBusy();
+  void profileMemRefresh();
+  void profileMemRead();
+  void profileMemWrite();
+  void profileMemWaitCycles(int cycles);
+  void profileMemInputQ(int cycles);
+  void profileMemBankQ(int cycles);
+  void profileMemArbWait(int cycles);
+  void profileMemRandBusy();
+  void profileMemNotOld();
+
+  void print(ostream& out) const;
+private:
+  // Private Methods
+
+  // Private copy constructor and assignment operator
+  MemCntrlProfiler(const MemCntrlProfiler& obj);
+  MemCntrlProfiler& operator=(const MemCntrlProfiler& obj);
+
+  // Data Members (m_ prefix)
+  string m_description;
+  uint64 m_memReq;
+  uint64 m_memBankBusy;
+  uint64 m_memBusBusy;
+  uint64 m_memTfawBusy;
+  uint64 m_memReadWriteBusy;
+  uint64 m_memDataBusBusy;
+  uint64 m_memRefresh;
+  uint64 m_memRead;
+  uint64 m_memWrite;
+  uint64 m_memWaitCycles;
+  uint64 m_memInputQ;
+  uint64 m_memBankQ;
+  uint64 m_memArbWait;
+  uint64 m_memRandBusy;
+  uint64 m_memNotOld;
+  Vector<uint64> m_memBankCount;
+  int m_banks_per_rank;
+  int m_ranks_per_dimm;
+  int m_dimms_per_channel;
+};
+
+// Output operator declaration
+ostream& operator<<(ostream& out, const MemCntrlProfiler& obj);
+
+// ******************* Definitions *******************
+
+// Output operator definition
+extern inline
+ostream& operator<<(ostream& out, const MemCntrlProfiler& obj)
+{
+  obj.print(out);
+  out << flush;
+  return out;
+}
+
+#endif //MEM_CNTRL_PROFILER_H
index a4f0a7c97d4aa887eb71bd3ba10933b67d589125..f09b932167683f00d5e7af294ebe9728dd3d3c92 100644 (file)
@@ -90,40 +90,6 @@ Profiler::Profiler(const Params *p)
 
   m_num_of_sequencers = p->num_of_sequencers;
 
-  //
-  // Initialize the memory controller profiler structs
-  //
-  m_mc_profilers.setSize(p->mem_cntrl_count);
-  for (int mem_cntrl = 0; mem_cntrl < p->mem_cntrl_count; mem_cntrl++) {
-    m_mc_profilers[mem_cntrl] = new memory_control_profiler;
-    m_mc_profilers[mem_cntrl]->m_memReq = 0;
-    m_mc_profilers[mem_cntrl]->m_memBankBusy = 0;
-    m_mc_profilers[mem_cntrl]->m_memBusBusy = 0;
-    m_mc_profilers[mem_cntrl]->m_memReadWriteBusy = 0;
-    m_mc_profilers[mem_cntrl]->m_memDataBusBusy = 0;
-    m_mc_profilers[mem_cntrl]->m_memTfawBusy = 0;
-    m_mc_profilers[mem_cntrl]->m_memRefresh = 0;
-    m_mc_profilers[mem_cntrl]->m_memRead = 0;
-    m_mc_profilers[mem_cntrl]->m_memWrite = 0;
-    m_mc_profilers[mem_cntrl]->m_memWaitCycles = 0;
-    m_mc_profilers[mem_cntrl]->m_memInputQ = 0;
-    m_mc_profilers[mem_cntrl]->m_memBankQ = 0;
-    m_mc_profilers[mem_cntrl]->m_memArbWait = 0;
-    m_mc_profilers[mem_cntrl]->m_memRandBusy = 0;
-    m_mc_profilers[mem_cntrl]->m_memNotOld = 0;
-
-    m_mc_profilers[mem_cntrl]->m_banks_per_rank = p->banks_per_rank;
-    m_mc_profilers[mem_cntrl]->m_ranks_per_dimm = p->ranks_per_dimm;
-    m_mc_profilers[mem_cntrl]->m_dimms_per_channel = 
-      p->dimms_per_channel;
-
-    int totalBanks = p->banks_per_rank * 
-                     p->ranks_per_dimm * 
-                     p->dimms_per_channel;
-
-    m_mc_profilers[mem_cntrl]->m_memBankCount.setSize(totalBanks);
-  }    
-
   m_hot_lines = false;
   m_all_instructions = false;
 
@@ -144,12 +110,6 @@ Profiler::~Profiler()
     delete m_periodic_output_file_ptr;
   }
 
-  for (int mem_cntrl = 0; 
-       mem_cntrl < m_mc_profilers.size(); 
-       mem_cntrl++) {
-    delete m_mc_profilers[mem_cntrl];
-  }
-
   delete m_requestProfileMap_ptr;
 }
 
@@ -363,64 +323,6 @@ void Profiler::printStats(ostream& out, bool short_stats)
 
   out << endl;
 
-  for (int mem_cntrl = 0; 
-       mem_cntrl < m_mc_profilers.size(); 
-       mem_cntrl++) {
-    uint64 m_memReq = m_mc_profilers[mem_cntrl]->m_memReq;
-    uint64 m_memRefresh = m_mc_profilers[mem_cntrl]->m_memRefresh;
-    uint64 m_memInputQ = m_mc_profilers[mem_cntrl]->m_memInputQ;
-    uint64 m_memBankQ = m_mc_profilers[mem_cntrl]->m_memBankQ;
-    uint64 m_memWaitCycles = m_mc_profilers[mem_cntrl]->m_memWaitCycles;
-    uint64 m_memRead = m_mc_profilers[mem_cntrl]->m_memRead;
-    uint64 m_memWrite = m_mc_profilers[mem_cntrl]->m_memWrite;
-    uint64 m_memBankBusy = m_mc_profilers[mem_cntrl]->m_memBankBusy;
-    uint64 m_memRandBusy = m_mc_profilers[mem_cntrl]->m_memRandBusy;
-    uint64 m_memNotOld = m_mc_profilers[mem_cntrl]->m_memNotOld;
-    uint64 m_memArbWait = m_mc_profilers[mem_cntrl]->m_memArbWait;
-    uint64 m_memBusBusy = m_mc_profilers[mem_cntrl]->m_memBusBusy;
-    uint64 m_memTfawBusy = m_mc_profilers[mem_cntrl]->m_memTfawBusy;
-    uint64 m_memReadWriteBusy = m_mc_profilers[mem_cntrl]->m_memReadWriteBusy;
-    uint64 m_memDataBusBusy = m_mc_profilers[mem_cntrl]->m_memDataBusBusy;
-    Vector<uint64> m_memBankCount = m_mc_profilers[mem_cntrl]->m_memBankCount;
-
-    if (m_memReq || m_memRefresh) {    // if there's a memory controller at all
-      uint64 total_stalls = m_memInputQ + m_memBankQ + m_memWaitCycles;
-      double stallsPerReq = total_stalls * 1.0 / m_memReq;
-      out << "Memory control " << mem_cntrl << ":" << endl;
-      out << "  memory_total_requests: " << m_memReq << endl;  // does not include refreshes
-      out << "  memory_reads: " << m_memRead << endl;
-      out << "  memory_writes: " << m_memWrite << endl;
-      out << "  memory_refreshes: " << m_memRefresh << endl;
-      out << "  memory_total_request_delays: " << total_stalls << endl;
-      out << "  memory_delays_per_request: " << stallsPerReq << endl;
-      out << "  memory_delays_in_input_queue: " << m_memInputQ << endl;
-      out << "  memory_delays_behind_head_of_bank_queue: " << m_memBankQ << endl;
-      out << "  memory_delays_stalled_at_head_of_bank_queue: " << m_memWaitCycles << endl;
-      // Note:  The following "memory stalls" entries are a breakdown of the
-      // cycles which already showed up in m_memWaitCycles.  The order is
-      // significant; it is the priority of attributing the cycles.
-      // For example, bank_busy is before arbitration because if the bank was
-      // busy, we didn't even check arbitration.
-      // Note:  "not old enough" means that since we grouped waiting heads-of-queues
-      // into batches to avoid starvation, a request in a newer batch
-      // didn't try to arbitrate yet because there are older requests waiting.
-      out << "  memory_stalls_for_bank_busy: " << m_memBankBusy << endl;
-      out << "  memory_stalls_for_random_busy: " << m_memRandBusy << endl;
-      out << "  memory_stalls_for_anti_starvation: " << m_memNotOld << endl;
-      out << "  memory_stalls_for_arbitration: " << m_memArbWait << endl;
-      out << "  memory_stalls_for_bus: " << m_memBusBusy << endl;
-      out << "  memory_stalls_for_tfaw: " << m_memTfawBusy << endl;
-      out << "  memory_stalls_for_read_write_turnaround: " << m_memReadWriteBusy << endl;
-      out << "  memory_stalls_for_read_read_turnaround: " << m_memDataBusBusy << endl;
-      out << "  accesses_per_bank: ";
-      for (int bank=0; bank < m_memBankCount.size(); bank++) {
-        out << m_memBankCount[bank] << "  ";
-        //if ((bank % 8) == 7) out << "                     " << endl;
-      }
-      out << endl;
-      out << endl;
-    }
-  }
   if (!short_stats) {
     out << "Busy Controller Counts:" << endl;
     for(int i=0; i < MachineType_NUM; i++) {
@@ -643,34 +545,6 @@ void Profiler::clearStats()
   m_outstanding_requests.clear();
   m_outstanding_persistent_requests.clear();
 
-//added by SS
-  vector<string>::iterator it;
-
-  for (int mem_cntrl = 0; 
-       mem_cntrl < m_mc_profilers.size(); 
-       mem_cntrl++) {
-    m_mc_profilers[mem_cntrl]->m_memReq = 0;
-    m_mc_profilers[mem_cntrl]->m_memBankBusy = 0;
-    m_mc_profilers[mem_cntrl]->m_memBusBusy = 0;
-    m_mc_profilers[mem_cntrl]->m_memTfawBusy = 0;
-    m_mc_profilers[mem_cntrl]->m_memReadWriteBusy = 0;
-    m_mc_profilers[mem_cntrl]->m_memDataBusBusy = 0;
-    m_mc_profilers[mem_cntrl]->m_memRefresh = 0;
-    m_mc_profilers[mem_cntrl]->m_memRead = 0;
-    m_mc_profilers[mem_cntrl]->m_memWrite = 0;
-    m_mc_profilers[mem_cntrl]->m_memWaitCycles = 0;
-    m_mc_profilers[mem_cntrl]->m_memInputQ = 0;
-    m_mc_profilers[mem_cntrl]->m_memBankQ = 0;
-    m_mc_profilers[mem_cntrl]->m_memArbWait = 0;
-    m_mc_profilers[mem_cntrl]->m_memRandBusy = 0;
-    m_mc_profilers[mem_cntrl]->m_memNotOld = 0;
-
-    for (int bank=0; 
-         bank < m_mc_profilers[mem_cntrl]->m_memBankCount.size(); 
-         bank++) {
-        m_mc_profilers[mem_cntrl]->m_memBankCount[bank] = 0;
-    }
-  }
   // Flush the prefetches through the system - used so that there are no outstanding requests after stats are cleared
   //g_eventQueue_ptr->triggerAllEvents();
 
@@ -863,68 +737,6 @@ int64 Profiler::getTotalTransactionsExecuted() const {
   return m_perProcEndTransaction.sum();
 }
 
-// For MemoryControl:
-void Profiler::profileMemReq(int mem_cntrl, int bank) {
-  m_mc_profilers[mem_cntrl]->m_memReq++;
-  m_mc_profilers[mem_cntrl]->m_memBankCount[bank]++;
-}
-
-void Profiler::profileMemBankBusy(int mem_cntrl) {    
-  m_mc_profilers[mem_cntrl]->m_memBankBusy++; 
-}
-
-void Profiler::profileMemBusBusy(int mem_cntrl) {    
-  m_mc_profilers[mem_cntrl]->m_memBusBusy++; 
-}
-
-void Profiler::profileMemReadWriteBusy(int mem_cntrl) {    
-  m_mc_profilers[mem_cntrl]->m_memReadWriteBusy++; 
-}
-
-void Profiler::profileMemDataBusBusy(int mem_cntrl) {    
-  m_mc_profilers[mem_cntrl]->m_memDataBusBusy++; 
-}
-
-void Profiler::profileMemTfawBusy(int mem_cntrl) {    
-  m_mc_profilers[mem_cntrl]->m_memTfawBusy++; 
-}
-
-void Profiler::profileMemRefresh(int mem_cntrl) {    
-  m_mc_profilers[mem_cntrl]->m_memRefresh++; 
-}
-
-void Profiler::profileMemRead(int mem_cntrl) {    
-  m_mc_profilers[mem_cntrl]->m_memRead++; 
-}
-
-void Profiler::profileMemWrite(int mem_cntrl) {    
-  m_mc_profilers[mem_cntrl]->m_memWrite++; 
-}
-
-void Profiler::profileMemWaitCycles(int mem_cntrl, int cycles) {
-  m_mc_profilers[mem_cntrl]->m_memWaitCycles += cycles; 
-}
-
-void Profiler::profileMemInputQ(int mem_cntrl, int cycles) {    
-  m_mc_profilers[mem_cntrl]->m_memInputQ += cycles; 
-}
-
-void Profiler::profileMemBankQ(int mem_cntrl, int cycles) {    
-  m_mc_profilers[mem_cntrl]->m_memBankQ += cycles; 
-}
-
-void Profiler::profileMemArbWait(int mem_cntrl, int cycles) {    
-  m_mc_profilers[mem_cntrl]->m_memArbWait += cycles; 
-}
-
-void Profiler::profileMemRandBusy(int mem_cntrl) {    
-  m_mc_profilers[mem_cntrl]->m_memRandBusy++; 
-}
-
-void Profiler::profileMemNotOld(int mem_cntrl) {    
-  m_mc_profilers[mem_cntrl]->m_memNotOld++; 
-}
-
 
 Profiler *
 RubyProfilerParams::create()
index 4af0f559d5dbdbf2b33c52f8a959109a2032bf6c..b142e94a3b82271ab5d5b64799cb787a397a2877 100644 (file)
@@ -79,29 +79,6 @@ class AddressProfiler;
 
 template <class KEY_TYPE, class VALUE_TYPE> class Map;
 
-struct memory_control_profiler {
-  uint64 m_memReq;
-  uint64 m_memBankBusy;
-  uint64 m_memBusBusy;
-  uint64 m_memTfawBusy;
-  uint64 m_memReadWriteBusy;
-  uint64 m_memDataBusBusy;
-  uint64 m_memRefresh;
-  uint64 m_memRead;
-  uint64 m_memWrite;
-  uint64 m_memWaitCycles;
-  uint64 m_memInputQ;
-  uint64 m_memBankQ;
-  uint64 m_memArbWait;
-  uint64 m_memRandBusy;
-  uint64 m_memNotOld;
-  Vector<uint64> m_memBankCount;
-  int m_banks_per_rank;
-  int m_ranks_per_dimm;
-  int m_dimms_per_channel;
-};
-
-
 class Profiler : public SimObject, public Consumer {
 public:
   // Constructors
@@ -170,29 +147,11 @@ public:
     return m_ruby_start;
   }
 
-  // added for MemoryControl:
-  void profileMemReq(int mem_cntrl, int bank);
-  void profileMemBankBusy(int mem_cntrl);
-  void profileMemBusBusy(int mem_cntrl);
-  void profileMemTfawBusy(int mem_cntrl);
-  void profileMemReadWriteBusy(int mem_cntrl);
-  void profileMemDataBusBusy(int mem_cntrl);
-  void profileMemRefresh(int mem_cntrl);
-  void profileMemRead(int mem_cntrl);
-  void profileMemWrite(int mem_cntrl);
-  void profileMemWaitCycles(int mem_cntrl, int cycles);
-  void profileMemInputQ(int mem_cntrl, int cycles);
-  void profileMemBankQ(int mem_cntrl, int cycles);
-  void profileMemArbWait(int mem_cntrl, int cycles);
-  void profileMemRandBusy(int mem_cntrl);
-  void profileMemNotOld(int mem_cntrl);
   //added by SS
   bool getHotLines() { return m_hot_lines; }
   bool getAllInstructions() { return m_all_instructions; }
 
 private:
-  //added by SS
-  vector<string> m_memory_control_names;
 
   // Private copy constructor and assignment operator
   Profiler(const Profiler& obj);
@@ -255,10 +214,6 @@ private:
   int m_requests;
   Map <string, int>* m_requestProfileMap_ptr;
 
-  // added for MemoryControl:
-  //added by SS
-  Vector < memory_control_profiler* > m_mc_profilers;
-
   //added by SS
   bool m_hot_lines;
   bool m_all_instructions;
index 9d81d40148f8a31f049ce76860524fc72b25553a..f6a4da6f8d4c9af9054f4e2ce530177d0d4e324a 100644 (file)
@@ -7,12 +7,3 @@ class RubyProfiler(SimObject):
     hot_lines = Param.Bool(False, "")
     all_instructions = Param.Bool(False, "")
     num_of_sequencers = Param.Int("")
-    mem_cntrl_count = Param.Int(0, "")
-    banks_per_rank = Param.Int("")
-    ranks_per_dimm = Param.Int("")
-    dimms_per_channel = Param.Int("")
-
-class CacheProfiler(SimObject):
-    type = 'CacheProfiler'
-    cxx_class = 'CacheProfiler'
-    description = Param.String("")
index 41481e3cafc8312d6fd9b3e9da29479504de3675..121a360c925fce7ac46057050886898971ca2a66 100644 (file)
@@ -38,5 +38,6 @@ SimObject('Profiler.py')
 Source('AccessTraceForAddress.cc')
 Source('AddressProfiler.cc')
 Source('CacheProfiler.cc')
+Source('MemCntrlProfiler.cc')
 Source('Profiler.cc')
 Source('StoreTrace.cc')
index 5cec5d6e61284c0e9097a3d19c141165e26e000b..209d6f6e27685cec63f4d94bd167301545803558 100644 (file)
@@ -9,4 +9,3 @@ class RubyCache(SimObject):
     latency = Param.Int("");
     assoc = Param.Int("");
     replacement_policy = Param.String("PSEUDO_LRU", "");
-    cache_profiler = Param.CacheProfiler("");
index 60783c43371a26c13240ce48d840a93fd4879c43..8c51121837ecca7d8056a4f82300760b6959ad2a 100644 (file)
@@ -57,7 +57,7 @@ CacheMemory::CacheMemory(const Params *p)
     m_latency = p->latency;
     m_cache_assoc = p->assoc;
     m_policy = p->replacement_policy;
-    m_profiler_ptr = p->cache_profiler;
+    m_profiler_ptr = new CacheProfiler(name());
 }
 
 
index 0a7b93e6f1b01f98b58648cc7ded5900b074ca1f..0f12efc36cab348d011f6e40f0e233596e7738cf 100644 (file)
@@ -154,7 +154,6 @@ ostream& operator<<(ostream& out, const MemoryControl& obj)
 MemoryControl::MemoryControl(const Params *p)
     : SimObject(p)
 {
-    m_version = p->version;
     m_mem_bus_cycle_multiplier = p->mem_bus_cycle_multiplier;
     m_banks_per_rank = p->banks_per_rank;
     m_ranks_per_dimm = p->ranks_per_dimm;
@@ -172,6 +171,11 @@ MemoryControl::MemoryControl(const Params *p)
     m_tFaw = p->tFaw;
     m_mem_random_arbitrate = p->mem_random_arbitrate;
     m_mem_fixed_delay = p->mem_fixed_delay;
+
+    m_profiler_ptr = new MemCntrlProfiler(name(),
+                                          m_banks_per_rank,
+                                          m_ranks_per_dimm,
+                                          m_dimms_per_channel);
 }
 
 void MemoryControl::init()
@@ -179,8 +183,6 @@ void MemoryControl::init()
   m_msg_counter = 0;
 
   m_debug = 0;
-  //if (m_version == 0) m_debug = 1;
-
 
   assert(m_tFaw <= 62); // must fit in a uint64 shift register
 
@@ -235,6 +237,7 @@ MemoryControl::~MemoryControl () {
   delete [] m_bankQueues;
   delete [] m_bankBusyCounter;
   delete [] m_oldRequest;
+  delete m_profiler_ptr;
 }
 
 
@@ -268,7 +271,7 @@ void MemoryControl::enqueueMemRef (MemoryNode& memRef) {
     printf("bank =%3x\n", bank);
   }
 
-  g_system_ptr->getProfiler()->profileMemReq(m_version, bank);
+  m_profiler_ptr->profileMemReq(bank);
   m_input_queue.push_back(memRef);
   if (!m_awakened) {
     g_eventQueue_ptr->scheduleEvent(this, 1);
@@ -321,6 +324,7 @@ void MemoryControl::print (ostream& out) const {
 
 
 void MemoryControl::printConfig (ostream& out) {
+  out << "Memory Control " << name() << ":" << endl;
   out << "  Ruby cycles per memory cycle: " << m_mem_bus_cycle_multiplier << endl;
   out << "  Basic read latency: " << m_mem_ctl_latency << endl;
   if (m_mem_fixed_delay) {
@@ -348,6 +352,16 @@ void MemoryControl::setDebug (int debugFlag) {
   m_debug = debugFlag;
 }
 
+void MemoryControl::clearStats() const
+{
+  m_profiler_ptr->clearStats();
+}
+
+void MemoryControl::printStats(ostream& out) const
+{
+  m_profiler_ptr->printStats(out);
+}
+
 
 // ****************************************************************
 
@@ -394,19 +408,19 @@ int MemoryControl::getRank (int bank) {
 
 bool MemoryControl::queueReady (int bank) {
   if ((m_bankBusyCounter[bank] > 0) && !m_mem_fixed_delay) {
-    g_system_ptr->getProfiler()->profileMemBankBusy(m_version);
+    m_profiler_ptr->profileMemBankBusy();
     //if (m_debug) printf("  bank %x busy %d\n", bank, m_bankBusyCounter[bank]);
     return false;
   }
   if (m_mem_random_arbitrate >= 2) {
     if ((random() % 100) < m_mem_random_arbitrate) {
-      g_system_ptr->getProfiler()->profileMemRandBusy(m_version);
+      m_profiler_ptr->profileMemRandBusy();
       return false;
     }
   }
   if (m_mem_fixed_delay) return true;
   if ((m_ageCounter > (2 * m_bank_busy_time)) && !m_oldRequest[bank]) {
-    g_system_ptr->getProfiler()->profileMemNotOld(m_version);
+    m_profiler_ptr->profileMemNotOld();
     return false;
   }
   if (m_busBusyCounter_Basic == m_basic_bus_busy_time) {
@@ -415,26 +429,26 @@ bool MemoryControl::queueReady (int bank) {
     // a bus wait.  This is a little inaccurate since it MIGHT
     // have also been blocked waiting for a read-write or a
     // read-read instead, but it's pretty close.
-    g_system_ptr->getProfiler()->profileMemArbWait(m_version, 1);
+    m_profiler_ptr->profileMemArbWait(1);
     return false;
   }
   if (m_busBusyCounter_Basic > 0) {
-    g_system_ptr->getProfiler()->profileMemBusBusy(m_version);
+    m_profiler_ptr->profileMemBusBusy();
     return false;
   }
   int rank = getRank(bank);
   if (m_tfaw_count[rank] >= ACTIVATE_PER_TFAW) {
-    g_system_ptr->getProfiler()->profileMemTfawBusy(m_version);
+    m_profiler_ptr->profileMemTfawBusy();
     return false;
   }
   bool write = !m_bankQueues[bank].front().m_is_mem_read;
   if (write && (m_busBusyCounter_Write > 0)) {
-    g_system_ptr->getProfiler()->profileMemReadWriteBusy(m_version);
+    m_profiler_ptr->profileMemReadWriteBusy();
     return false;
   }
   if (!write && (rank != m_busBusy_WhichRank)
              && (m_busBusyCounter_ReadNewRank > 0)) {
-    g_system_ptr->getProfiler()->profileMemDataBusBusy(m_version);
+    m_profiler_ptr->profileMemDataBusBusy();
     return false;
   }
   return true;
@@ -459,7 +473,7 @@ bool MemoryControl::issueRefresh (int bank) {
     //uint64 current_time = g_eventQueue_ptr->getTime();
     //printf("    Refresh bank %3x at %lld\n", bank, current_time);
   //}
-  g_system_ptr->getProfiler()->profileMemRefresh(m_version);
+  m_profiler_ptr->profileMemRefresh();
   m_need_refresh--;
   m_refresh_bank++;
   if (m_refresh_bank >= m_total_banks) m_refresh_bank = 0;
@@ -503,12 +517,12 @@ void MemoryControl::issueRequest (int bank) {
   m_bankBusyCounter[bank] = m_bank_busy_time;
   m_busBusy_WhichRank = rank;
   if (req.m_is_mem_read) {
-    g_system_ptr->getProfiler()->profileMemRead(m_version);
+    m_profiler_ptr->profileMemRead();
     m_busBusyCounter_Basic = m_basic_bus_busy_time;
     m_busBusyCounter_Write = m_basic_bus_busy_time + m_read_write_delay;
     m_busBusyCounter_ReadNewRank = m_basic_bus_busy_time + m_rank_rank_delay;
   } else {
-    g_system_ptr->getProfiler()->profileMemWrite(m_version);
+    m_profiler_ptr->profileMemWrite();
     m_busBusyCounter_Basic = m_basic_bus_busy_time;
     m_busBusyCounter_Write = m_basic_bus_busy_time;
     m_busBusyCounter_ReadNewRank = m_basic_bus_busy_time;
@@ -577,7 +591,7 @@ void MemoryControl::executeCycle () {
     issueRefresh(m_roundRobin);
     int qs = m_bankQueues[m_roundRobin].size();
     if (qs > 1) {
-      g_system_ptr->getProfiler()->profileMemBankQ(m_version, qs-1);
+      m_profiler_ptr->profileMemBankQ(qs-1);
     }
     if (qs > 0) {
       m_idleCount = IDLECOUNT_MAX_VALUE; // we're not idle if anything is queued
@@ -586,14 +600,14 @@ void MemoryControl::executeCycle () {
         issueRequest(m_roundRobin);
         banksIssued++;
         if (m_mem_fixed_delay) {
-          g_system_ptr->getProfiler()->profileMemWaitCycles(m_version, m_mem_fixed_delay);
+          m_profiler_ptr->profileMemWaitCycles(m_mem_fixed_delay);
         }
       }
     }
   }
 
   // memWaitCycles is a redundant catch-all for the specific counters in queueReady
-  g_system_ptr->getProfiler()->profileMemWaitCycles(m_version, queueHeads - banksIssued);
+  m_profiler_ptr->profileMemWaitCycles(queueHeads - banksIssued);
 
   // Check input queue and move anything to bank queues if not full.
   // Since this is done here at the end of the cycle, there will always
@@ -610,7 +624,7 @@ void MemoryControl::executeCycle () {
       m_input_queue.pop_front();
       m_bankQueues[bank].push_back(req);
     }
-    g_system_ptr->getProfiler()->profileMemInputQ(m_version, m_input_queue.size());
+    m_profiler_ptr->profileMemInputQ(m_input_queue.size());
   }
 }
 
index c875c0bbc0dcd950232f30881b3f5cf60467bdc0..b96055cb15cb69e3a0396ef2dcbeab38cb8c565d 100644 (file)
@@ -42,7 +42,7 @@
 #include "mem/ruby/common/Global.hh"
 #include "mem/gems_common/Map.hh"
 #include "mem/ruby/common/Address.hh"
-#include "mem/ruby/profiler/Profiler.hh"
+#include "mem/ruby/profiler/MemCntrlProfiler.hh"
 #include "mem/ruby/system/System.hh"
 #include "mem/ruby/slicc_interface/Message.hh"
 #include "mem/gems_common/util.hh"
@@ -99,6 +99,8 @@ public:
   void printConfig (ostream& out);
   void print (ostream& out) const;
   void setDebug (int debugFlag);
+  void clearStats() const;
+  void printStats(ostream& out) const;
 
 
   //added by SS
@@ -123,7 +125,6 @@ private:
 
   // data members
   Consumer* m_consumer_ptr;  // Consumer to signal a wakeup()
-  int m_version;
   string m_description;
   int m_msg_counter;
   int m_awakened;
@@ -178,6 +179,8 @@ private:
   int m_ageCounter;         // age of old requests; to detect starvation
   int m_idleCount;          // watchdog timer for shutting down
   int m_debug;              // turn on printf's
+
+  MemCntrlProfiler* m_profiler_ptr;
 };
 
 #endif  // MEMORY_CONTROL_H