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.
This commit is contained in:
Brad Beckmann 2010-01-29 20:29:22 -08:00
parent cfe41d0a1b
commit f88faa6c11
14 changed files with 356 additions and 302 deletions

View 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,

View 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,

View file

@ -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);
}

View file

@ -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();

View file

@ -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++;
}

View file

@ -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

View 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()

View 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;

View 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("")

View 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')

View file

@ -9,4 +9,3 @@ class RubyCache(SimObject):
latency = Param.Int("");
assoc = Param.Int("");
replacement_policy = Param.String("PSEUDO_LRU", "");
cache_profiler = Param.CacheProfiler("");

View 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());
}

View 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());
}
}

View 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