diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh --- a/src/mem/ruby/slicc_interface/AbstractController.hh +++ b/src/mem/ruby/slicc_interface/AbstractController.hh @@ -103,12 +103,6 @@ virtual void enqueuePrefetch(const Addr &, 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!");} - //! Initialize the message buffers. virtual void initNetQueues() = 0; @@ -181,19 +175,6 @@ Stats::Histogram m_delayHistogram; std::vector 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();} - }; - /** * Port that forwards requests and receives responses from the * memory controller. It has a queue of packets not yet sent. # Node ID 3796b26e6c20c1eaf37b8cc30050801e1e5a3e88 # Parent 1273aab7b1f3aad2709ae0ec3da32b9e7ca51022 diff --git a/src/mem/ruby/slicc_interface/AbstractController.cc b/src/mem/ruby/slicc_interface/AbstractController.cc --- a/src/mem/ruby/slicc_interface/AbstractController.cc +++ b/src/mem/ruby/slicc_interface/AbstractController.cc @@ -48,11 +48,6 @@ { assert(isPowerOf2(m_block_size_bytes)); - 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/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -306,7 +306,6 @@ void wakeup(); void resetStats(); void regStats(); - void collateStats(); void recordCacheTrace(int cntrl, CacheRecorder* tr); Sequencer* getCPUSequencer() const; @@ -364,12 +363,9 @@ code(''' Addr addr); -int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; -int m_event_counters[${ident}_Event_NUM]; +Stats::Scalar m_counters[${ident}_State_NUM][${ident}_Event_NUM]; +Stats::Scalar m_event_counters[${ident}_Event_NUM]; bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; - -static std::vector eventVec; -static std::vector > transVec; static int m_num_controllers; // Internal functions @@ -500,8 +496,6 @@ } int $c_ident::m_num_controllers = 0; -std::vector $c_ident::eventVec; -std::vector > $c_ident::transVec; // for adding information to the protocol debug trace stringstream ${ident}_transitionComment; @@ -546,12 +540,8 @@ for (int state = 0; state < ${ident}_State_NUM; state++) { for (int event = 0; event < ${ident}_Event_NUM; event++) { m_possible[state][event] = false; - m_counters[state][event] = 0; } } -for (int event = 0; event < ${ident}_Event_NUM; event++) { - m_event_counters[event] = 0; -} ''') code.dedent() code(''' @@ -734,54 +724,12 @@ { AbstractController::regStats(); - if (m_version == 0) { - for (${ident}_Event event = ${ident}_Event_FIRST; - event < ${ident}_Event_NUM; ++event) { - Stats::Vector *t = new Stats::Vector(); - t->init(m_num_controllers); - t->name(params()->ruby_system->name() + ".${c_ident}." + - ${ident}_Event_to_string(event)); - t->flags(Stats::pdf | Stats::total | Stats::oneline | - Stats::nozero); - - eventVec.push_back(t); - } - - for (${ident}_State state = ${ident}_State_FIRST; - state < ${ident}_State_NUM; ++state) { - - transVec.push_back(std::vector()); - - for (${ident}_Event event = ${ident}_Event_FIRST; - event < ${ident}_Event_NUM; ++event) { - - Stats::Vector *t = new Stats::Vector(); - t->init(m_num_controllers); - t->name(params()->ruby_system->name() + ".${c_ident}." + - ${ident}_State_to_string(state) + - "." + ${ident}_Event_to_string(event)); - - t->flags(Stats::pdf | Stats::total | Stats::oneline | - Stats::nozero); - transVec[state].push_back(t); - } - } - } -} - -void -$c_ident::collateStats() -{ for (${ident}_Event event = ${ident}_Event_FIRST; event < ${ident}_Event_NUM; ++event) { - for (unsigned int i = 0; i < m_num_controllers; ++i) { - RubySystem *rs = params()->ruby_system; - std::map::iterator it = - rs->m_abstract_controls[MachineType_${ident}].find(i); - assert(it != rs->m_abstract_controls[MachineType_${ident}].end()); - (*eventVec[event])[i] = - (($c_ident *)(*it).second)->getEventCount(event); - } + m_event_counters[event].name(name() + "." + + ${ident}_Event_to_string(event)); + m_event_counters[event].flags(Stats::pdf | Stats::total | + Stats::oneline | Stats::nozero | Stats::collate); } for (${ident}_State state = ${ident}_State_FIRST; @@ -790,14 +738,12 @@ for (${ident}_Event event = ${ident}_Event_FIRST; event < ${ident}_Event_NUM; ++event) { - for (unsigned int i = 0; i < m_num_controllers; ++i) { - RubySystem *rs = params()->ruby_system; - std::map::iterator it = - rs->m_abstract_controls[MachineType_${ident}].find(i); - assert(it != rs->m_abstract_controls[MachineType_${ident}].end()); - (*transVec[state][event])[i] = - (($c_ident *)(*it).second)->getTransitionCount(state, event); - } + m_counters[state][event].name(name() + "." + + ${ident}_State_to_string(state) + "." + + ${ident}_Event_to_string(event)); + + m_counters[state][event].flags(Stats::pdf | Stats::total | + Stats::oneline | Stats::nozero | Stats::collate); } } } @@ -816,25 +762,12 @@ m_possible[state][event] = true; } -uint64_t -$c_ident::getEventCount(${ident}_Event event) -{ - return m_event_counters[event]; -} - bool $c_ident::isPossible(${ident}_State state, ${ident}_Event event) { return m_possible[state][event]; } -uint64_t -$c_ident::getTransitionCount(${ident}_State state, - ${ident}_Event event) -{ - return m_counters[state][event]; -} - int $c_ident::getNumControllers() { @@ -861,16 +794,6 @@ void $c_ident::resetStats() { - for (int state = 0; state < ${ident}_State_NUM; state++) { - for (int event = 0; event < ${ident}_Event_NUM; event++) { - m_counters[state][event] = 0; - } - } - - for (int event = 0; event < ${ident}_Event_NUM; event++) { - m_event_counters[event] = 0; - } - AbstractController::resetStats(); } ''') diff --git a/src/python/m5/stats/__init__.py b/src/python/m5/stats/__init__.py --- a/src/python/m5/stats/__init__.py +++ b/src/python/m5/stats/__init__.py @@ -34,6 +34,11 @@ from m5.objects import Root from m5.util import attrdict, fatal +import os, sys +import string +from ConfigParser import ConfigParser +from collections import OrderedDict + outputList = [] def initText(filename, desc=True): output = internal.stats.initText(filename, desc) @@ -86,6 +91,58 @@ internal.stats.enable(); +def processRubySystem(config, sec): + child_dict = {} + children = string.split(config.get(sec, 'children')) + for child in children: + full_name = sec + "." + child + child_type = config.get(full_name, 'type') + if child_type in child_dict: + child_dict[child_type].append(full_name) + else: + child_dict[child_type] = [full_name] + + ruby_stats_output = "" + for (child_type, child_list) in child_dict.iteritems(): + if len(child_list) <= 1: + continue + + ruby_stats_dict = OrderedDict() + for stat in stats_list: + for child_name in child_list: + index = stat.name.find(child_name) + if index == -1: + continue + if not (stat.flags & flags.collate): + continue + + stats_key = sec + "." + child_type + \ + stat.name[index + len(child_name):] + if stats_key not in ruby_stats_dict: + if (not (stat.flags & flags.nozero)) or \ + (stat.value() != 0): + ruby_stats_dict[stats_key] = stat.value() + else: + ruby_stats_dict[stats_key] += stat.value() + + for (stat_key, stat_vals) in ruby_stats_dict.iteritems(): + ruby_stats_output += stat_key + "::total\t%d\n" % stat_vals + + return ruby_stats_output + +def collateRubyStats(): + from m5 import options + config = ConfigParser() + config_file_name = os.path.join(options.outdir, options.dump_config) + config.readfp(open(config_file_name)) + + ruby_stats_output = "" + for sec in config.sections(): + if config.get(sec, 'type') == 'RubySystem': + ruby_stats_output += processRubySystem(config, sec) + + return ruby_stats_output + def prepare(): '''Prepare all stats for data access. This must be done before dumping and serialization.''' @@ -93,6 +150,8 @@ for stat in stats_list: stat.prepare() + return collateRubyStats() + lastDump = 0 def dump(): '''Dump all statistics data to the registered outputs''' @@ -107,13 +166,16 @@ internal.stats.processDumpQueue() - prepare() + ruby_stats_output = prepare() for output in outputList: if output.valid(): output.begin() + for stat in stats_list: output.visit(stat) + + output.visit(ruby_stats_output) output.end() def reset(): @@ -140,4 +202,6 @@ 'dist' : 0x0080, 'nozero' : 0x0100, 'nonan' : 0x0200, + 'oneline' : 0x0400, + 'collate' : 0x0800, })