diff options
author | Brad Beckmann <Brad.Beckmann@amd.com> | 2010-01-29 20:29:22 -0800 |
---|---|---|
committer | Brad Beckmann <Brad.Beckmann@amd.com> | 2010-01-29 20:29:22 -0800 |
commit | f88faa6c11bbb5c5f95fe32ccffca73c7c4758c8 (patch) | |
tree | 73f1ccfa1f56d86a8787f6e04a8c2cb116167e8c | |
parent | cfe41d0a1bc3b778995cd1b22f8d58037300143b (diff) | |
download | gem5-f88faa6c11bbb5c5f95fe32ccffca73c7c4758c8.tar.xz |
ruby: cleaned up ruby profilers
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.
-rw-r--r-- | configs/ruby/MOESI_hammer.py | 11 | ||||
-rw-r--r-- | configs/ruby/Ruby.py | 15 | ||||
-rw-r--r-- | src/mem/ruby/profiler/CacheProfiler.cc | 13 | ||||
-rw-r--r-- | src/mem/ruby/profiler/CacheProfiler.hh | 7 | ||||
-rw-r--r-- | src/mem/ruby/profiler/MemCntrlProfiler.cc | 184 | ||||
-rw-r--r-- | src/mem/ruby/profiler/MemCntrlProfiler.hh | 123 | ||||
-rw-r--r-- | src/mem/ruby/profiler/Profiler.cc | 188 | ||||
-rw-r--r-- | src/mem/ruby/profiler/Profiler.hh | 45 | ||||
-rw-r--r-- | src/mem/ruby/profiler/Profiler.py | 9 | ||||
-rw-r--r-- | src/mem/ruby/profiler/SConscript | 1 | ||||
-rw-r--r-- | src/mem/ruby/system/Cache.py | 1 | ||||
-rw-r--r-- | src/mem/ruby/system/CacheMemory.cc | 2 | ||||
-rw-r--r-- | src/mem/ruby/system/MemoryControl.cc | 52 | ||||
-rw-r--r-- | src/mem/ruby/system/MemoryControl.hh | 7 |
14 files changed, 356 insertions, 302 deletions
diff --git a/configs/ruby/MOESI_hammer.py b/configs/ruby/MOESI_hammer.py index f35ab20c4..5273f597b 100644 --- a/configs/ruby/MOESI_hammer.py +++ b/configs/ruby/MOESI_hammer.py @@ -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, diff --git a/configs/ruby/Ruby.py b/configs/ruby/Ruby.py index 37c43602d..abc9a8df5 100644 --- a/configs/ruby/Ruby.py +++ b/configs/ruby/Ruby.py @@ -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, diff --git a/src/mem/ruby/profiler/CacheProfiler.cc b/src/mem/ruby/profiler/CacheProfiler.cc index a01d68050..474506734 100644 --- a/src/mem/ruby/profiler/CacheProfiler.cc +++ b/src/mem/ruby/profiler/CacheProfiler.cc @@ -43,10 +43,9 @@ #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); -} diff --git a/src/mem/ruby/profiler/CacheProfiler.hh b/src/mem/ruby/profiler/CacheProfiler.hh index eeed1153b..6c5fbb988 100644 --- a/src/mem/ruby/profiler/CacheProfiler.hh +++ b/src/mem/ruby/profiler/CacheProfiler.hh @@ -46,15 +46,12 @@ #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 index 000000000..693d43dc7 --- /dev/null +++ b/src/mem/ruby/profiler/MemCntrlProfiler.cc @@ -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 index 000000000..5343fac1b --- /dev/null +++ b/src/mem/ruby/profiler/MemCntrlProfiler.hh @@ -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 diff --git a/src/mem/ruby/profiler/Profiler.cc b/src/mem/ruby/profiler/Profiler.cc index a4f0a7c97..f09b93216 100644 --- a/src/mem/ruby/profiler/Profiler.cc +++ b/src/mem/ruby/profiler/Profiler.cc @@ -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() diff --git a/src/mem/ruby/profiler/Profiler.hh b/src/mem/ruby/profiler/Profiler.hh index 4af0f559d..b142e94a3 100644 --- a/src/mem/ruby/profiler/Profiler.hh +++ b/src/mem/ruby/profiler/Profiler.hh @@ -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; diff --git a/src/mem/ruby/profiler/Profiler.py b/src/mem/ruby/profiler/Profiler.py index 9d81d4014..f6a4da6f8 100644 --- a/src/mem/ruby/profiler/Profiler.py +++ b/src/mem/ruby/profiler/Profiler.py @@ -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("") diff --git a/src/mem/ruby/profiler/SConscript b/src/mem/ruby/profiler/SConscript index 41481e3ca..121a360c9 100644 --- a/src/mem/ruby/profiler/SConscript +++ b/src/mem/ruby/profiler/SConscript @@ -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') diff --git a/src/mem/ruby/system/Cache.py b/src/mem/ruby/system/Cache.py index 5cec5d6e6..209d6f6e2 100644 --- a/src/mem/ruby/system/Cache.py +++ b/src/mem/ruby/system/Cache.py @@ -9,4 +9,3 @@ class RubyCache(SimObject): latency = Param.Int(""); assoc = Param.Int(""); replacement_policy = Param.String("PSEUDO_LRU", ""); - cache_profiler = Param.CacheProfiler(""); diff --git a/src/mem/ruby/system/CacheMemory.cc b/src/mem/ruby/system/CacheMemory.cc index 60783c433..8c5112183 100644 --- a/src/mem/ruby/system/CacheMemory.cc +++ b/src/mem/ruby/system/CacheMemory.cc @@ -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()); } diff --git a/src/mem/ruby/system/MemoryControl.cc b/src/mem/ruby/system/MemoryControl.cc index 0a7b93e6f..0f12efc36 100644 --- a/src/mem/ruby/system/MemoryControl.cc +++ b/src/mem/ruby/system/MemoryControl.cc @@ -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()); } } diff --git a/src/mem/ruby/system/MemoryControl.hh b/src/mem/ruby/system/MemoryControl.hh index c875c0bbc..b96055cb1 100644 --- a/src/mem/ruby/system/MemoryControl.hh +++ b/src/mem/ruby/system/MemoryControl.hh @@ -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 |