summaryrefslogtreecommitdiff
path: root/src/mem/ruby
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/ruby')
-rw-r--r--src/mem/ruby/profiler/MemCntrlProfiler.cc215
-rw-r--r--src/mem/ruby/profiler/MemCntrlProfiler.hh41
-rw-r--r--src/mem/ruby/slicc_interface/AbstractController.cc6
-rw-r--r--src/mem/ruby/slicc_interface/AbstractController.hh29
-rw-r--r--src/mem/ruby/system/MemoryControl.hh3
-rw-r--r--src/mem/ruby/system/RubyMemoryControl.cc19
-rw-r--r--src/mem/ruby/system/RubyMemoryControl.hh3
7 files changed, 194 insertions, 122 deletions
diff --git a/src/mem/ruby/profiler/MemCntrlProfiler.cc b/src/mem/ruby/profiler/MemCntrlProfiler.cc
index 632842a2e..0cfc1e629 100644
--- a/src/mem/ruby/profiler/MemCntrlProfiler.cc
+++ b/src/mem/ruby/profiler/MemCntrlProfiler.cc
@@ -37,11 +37,6 @@ MemCntrlProfiler::MemCntrlProfiler(const string& 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.resize(totalBanks);
-
- clearStats();
}
MemCntrlProfiler::~MemCntrlProfiler()
@@ -49,87 +44,6 @@ MemCntrlProfiler::~MemCntrlProfiler()
}
void
-MemCntrlProfiler::printStats(ostream& out) const
-{
- if (!m_memReq && !m_memRefresh) {
- out << "Memory Controller: " << m_description
- << " no stats recorded." << endl
- << endl
- << endl;
- return;
- }
-
- // 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;
-
- // does not include refreshes
- out << " memory_total_requests: " << m_memReq << endl;
- 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] << " ";
- }
- 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++;
@@ -220,4 +134,133 @@ MemCntrlProfiler::profileMemNotOld()
m_memNotOld++;
}
+void
+MemCntrlProfiler::regStats()
+{
+ m_memReq
+ .name(m_description + ".memReq")
+ .desc("Total number of memory requests")
+ .flags(Stats::nozero)
+ ;
+
+ m_memRead
+ .name(m_description + ".memRead")
+ .desc("Number of memory reads")
+ .flags(Stats::nozero)
+ ;
+
+ m_memWrite
+ .name(m_description + ".memWrite")
+ .desc("Number of memory writes")
+ .flags(Stats::nozero)
+ ;
+
+ m_memRefresh
+ .name(m_description + ".memRefresh")
+ .desc("Number of memory refreshes")
+ .flags(Stats::nozero)
+ ;
+
+ m_memInputQ
+ .name(m_description + ".memInputQ")
+ .desc("Delay in the input queue")
+ .flags(Stats::nozero)
+ ;
+
+ m_memBankQ
+ .name(m_description + ".memBankQ")
+ .desc("Delay behind the head of the bank queue")
+ .flags(Stats::nozero)
+ ;
+
+ m_memWaitCycles
+ .name(m_description + ".memWaitCycles")
+ .desc("Delay stalled at the head of the bank queue")
+ .flags(Stats::nozero)
+ ;
+
+ m_totalStalls
+ .name(m_description + ".totalStalls")
+ .desc("Total number of stall cycles")
+ .flags(Stats::nozero)
+ ;
+
+ m_totalStalls = m_memInputQ + m_memBankQ + m_memWaitCycles;
+
+ m_stallsPerReq
+ .name(m_description + ".stallsPerReq")
+ .desc("Expected number of stall cycles per request")
+ .flags(Stats::nozero)
+ ;
+
+ m_stallsPerReq = m_totalStalls / m_memReq;
+
+ // 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.
+ m_memBankBusy
+ .name(m_description + ".memBankBusy")
+ .desc("memory stalls due to busy bank")
+ .flags(Stats::nozero)
+ ;
+
+ m_memRandBusy
+ .name(m_description + ".memRandBusy")
+ .desc("memory stalls due to busy random")
+ .flags(Stats::nozero)
+ ;
+
+ m_memNotOld
+ .name(m_description + ".memNotOld")
+ .desc("memory stalls due to anti starvation")
+ .flags(Stats::nozero)
+ ;
+
+ m_memArbWait
+ .name(m_description + ".memArbWait")
+ .desc("memory stalls due to arbitration")
+ .flags(Stats::nozero)
+ ;
+
+ m_memBusBusy
+ .name(m_description + ".memBusBusy")
+ .desc("memory stalls due to busy bus")
+ .flags(Stats::nozero)
+ ;
+
+ m_memTfawBusy
+ .name(m_description + ".memTfawBusy")
+ .desc("memory stalls for Tfaw")
+ .flags(Stats::nozero)
+ ;
+
+ m_memReadWriteBusy
+ .name(m_description + ".memReadWriteBusy")
+ .desc("memory stalls due to read write turnaround")
+ .flags(Stats::nozero)
+ ;
+
+ m_memDataBusBusy
+ .name(m_description + ".memDataBusBusy")
+ .desc("memory stalls due to read read turnaround")
+ .flags(Stats::nozero)
+ ;
+
+ int totalBanks = m_banks_per_rank * m_ranks_per_dimm * m_dimms_per_channel;
+ m_memBankCount
+ .init(totalBanks)
+ .name(m_description + ".memBankCount")
+ .desc("Number of accesses per bank")
+ .flags(Stats::pdf | Stats::total|Stats::oneline)
+ ;
+ for (int i = 0; i < totalBanks; i++) {
+ m_memBankCount.subname(i, "");
+ }
+}
diff --git a/src/mem/ruby/profiler/MemCntrlProfiler.hh b/src/mem/ruby/profiler/MemCntrlProfiler.hh
index a594e0d96..56e283f50 100644
--- a/src/mem/ruby/profiler/MemCntrlProfiler.hh
+++ b/src/mem/ruby/profiler/MemCntrlProfiler.hh
@@ -33,6 +33,7 @@
#include <string>
#include <vector>
+#include "base/statistics.hh"
#include "mem/ruby/common/TypeDefines.hh"
class MemCntrlProfiler
@@ -42,8 +43,7 @@ class MemCntrlProfiler
int ranks_per_dimm, int dimms_per_channel);
~MemCntrlProfiler();
- void printStats(std::ostream& out) const;
- void clearStats();
+ void regStats();
void profileMemReq(int bank);
void profileMemBankBusy();
@@ -69,22 +69,27 @@ private:
MemCntrlProfiler& operator=(const MemCntrlProfiler& obj);
std::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;
- std::vector<uint64> m_memBankCount;
+ Stats::Scalar m_memReq;
+ Stats::Scalar m_memRead;
+ Stats::Scalar m_memWrite;
+ Stats::Scalar m_memRefresh;
+
+ Stats::Scalar m_memWaitCycles;
+ Stats::Scalar m_memInputQ;
+ Stats::Scalar m_memBankQ;
+ Stats::Formula m_totalStalls;
+ Stats::Formula m_stallsPerReq;
+
+ Stats::Scalar m_memBankBusy;
+ Stats::Scalar m_memBusBusy;
+ Stats::Scalar m_memTfawBusy;
+ Stats::Scalar m_memReadWriteBusy;
+ Stats::Scalar m_memDataBusBusy;
+ Stats::Scalar m_memArbWait;
+ Stats::Scalar m_memRandBusy;
+ Stats::Scalar m_memNotOld;
+ Stats::Vector m_memBankCount;
+
int m_banks_per_rank;
int m_ranks_per_dimm;
int m_dimms_per_channel;
diff --git a/src/mem/ruby/slicc_interface/AbstractController.cc b/src/mem/ruby/slicc_interface/AbstractController.cc
index 6e99a72bb..930f3a70f 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.cc
+++ b/src/mem/ruby/slicc_interface/AbstractController.cc
@@ -40,6 +40,12 @@ AbstractController::AbstractController(const Params *p)
m_recycle_latency = p->recycle_latency;
m_number_of_TBEs = p->number_of_TBEs;
m_is_blocking = false;
+
+ if (m_version == 0) {
+ // Combine the statistics from all controllers
+ // of this particular type.
+ Stats::registerDumpCallback(new StatsCallback(this));
+ }
}
void
diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh
index e2471777b..079979bdf 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.hh
+++ b/src/mem/ruby/slicc_interface/AbstractController.hh
@@ -32,6 +32,7 @@
#include <iostream>
#include <string>
+#include "base/callback.hh"
#include "mem/protocol/AccessPermission.hh"
#include "mem/ruby/buffers/MessageBuffer.hh"
#include "mem/ruby/common/Address.hh"
@@ -54,6 +55,7 @@ class AbstractController : public ClockedObject, public Consumer
AbstractController(const Params *p);
void init();
const Params *params() const { return (const Params *)_params; }
+
virtual MessageBuffer* getMandatoryQueue() const = 0;
virtual const int & getVersion() const = 0;
virtual const std::string toString() const = 0; // returns text version of
@@ -68,8 +70,9 @@ class AbstractController : public ClockedObject, public Consumer
virtual void print(std::ostream & out) const = 0;
virtual void printStats(std::ostream & out) const = 0;
virtual void wakeup() = 0;
- // virtual void dumpStats(std::ostream & out) = 0;
virtual void clearStats() = 0;
+ virtual void regStats() = 0;
+
virtual void recordCacheTrace(int cntrl, CacheRecorder* tr) = 0;
virtual Sequencer* getSequencer() const = 0;
@@ -86,6 +89,12 @@ class AbstractController : public ClockedObject, public Consumer
virtual void enqueuePrefetch(const Address&, const RubyRequestType&)
{ fatal("Prefetches not implemented!");}
+ //! Function for collating statistics from all the controllers of this
+ //! particular type. This function should only be called from the
+ //! version 0 of this controller type.
+ virtual void collateStats()
+ {fatal("collateStats() should be overridden!");}
+
public:
MachineID getMachineID() const { return m_machineID; }
uint64_t getFullyBusyCycles() const { return m_fully_busy_cycles; }
@@ -154,6 +163,24 @@ class AbstractController : public ClockedObject, public Consumer
//! cares for
Histogram m_delayHistogram;
std::vector<Histogram> m_delayVCHistogram;
+
+ //! Callback class used for collating statistics from all the
+ //! controller of this type.
+ class StatsCallback : public Callback
+ {
+ private:
+ AbstractController *ctr;
+
+ public:
+ virtual ~StatsCallback() {}
+
+ StatsCallback(AbstractController *_ctr)
+ : ctr(_ctr)
+ {
+ }
+
+ void process() {ctr->collateStats();}
+ };
};
#endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCONTROLLER_HH__
diff --git a/src/mem/ruby/system/MemoryControl.hh b/src/mem/ruby/system/MemoryControl.hh
index daa5b61fc..6dc32b661 100644
--- a/src/mem/ruby/system/MemoryControl.hh
+++ b/src/mem/ruby/system/MemoryControl.hh
@@ -75,9 +75,6 @@ class MemoryControl : public ClockedObject, public Consumer
virtual bool areNSlotsAvailable(int n) = 0; // infinite queue length
virtual void print(std::ostream& out) const = 0;
- virtual void clearStats() const = 0;
- virtual void printStats(std::ostream& out) const = 0;
-
virtual void regStats() {};
virtual const int getChannel(const physical_address_t addr) const = 0;
diff --git a/src/mem/ruby/system/RubyMemoryControl.cc b/src/mem/ruby/system/RubyMemoryControl.cc
index 5ffc60e2b..84126a8f5 100644
--- a/src/mem/ruby/system/RubyMemoryControl.cc
+++ b/src/mem/ruby/system/RubyMemoryControl.cc
@@ -221,6 +221,7 @@ RubyMemoryControl::init()
m_tfaw_count[i] = 0;
}
}
+
void
RubyMemoryControl::reset()
{
@@ -359,18 +360,6 @@ RubyMemoryControl::print(ostream& out) const
{
}
-void
-RubyMemoryControl::clearStats() const
-{
- m_profiler_ptr->clearStats();
-}
-
-void
-RubyMemoryControl::printStats(ostream& out) const
-{
- m_profiler_ptr->printStats(out);
-}
-
// Queue up a completed request to send back to directory
void
RubyMemoryControl::enqueueToDirectory(MemoryNode req, Cycles latency)
@@ -789,6 +778,12 @@ RubyMemoryControl::functionalWriteBuffers(Packet *pkt)
return num_functional_writes;
}
+void
+RubyMemoryControl::regStats()
+{
+ m_profiler_ptr->regStats();
+}
+
RubyMemoryControl *
RubyMemoryControlParams::create()
{
diff --git a/src/mem/ruby/system/RubyMemoryControl.hh b/src/mem/ruby/system/RubyMemoryControl.hh
index d0dfa5b8d..7be74583a 100644
--- a/src/mem/ruby/system/RubyMemoryControl.hh
+++ b/src/mem/ruby/system/RubyMemoryControl.hh
@@ -81,8 +81,7 @@ class RubyMemoryControl : public MemoryControl
bool areNSlotsAvailable(int n) { return true; }; // infinite queue length
void print(std::ostream& out) const;
- void clearStats() const;
- void printStats(std::ostream& out) const;
+ void regStats();
const int getBank(const physical_address_t addr) const;
const int getRank(const physical_address_t addr) const;