diff options
-rw-r--r-- | src/mem/ruby/profiler/MemCntrlProfiler.cc | 215 | ||||
-rw-r--r-- | src/mem/ruby/profiler/MemCntrlProfiler.hh | 41 | ||||
-rw-r--r-- | src/mem/ruby/slicc_interface/AbstractController.cc | 6 | ||||
-rw-r--r-- | src/mem/ruby/slicc_interface/AbstractController.hh | 29 | ||||
-rw-r--r-- | src/mem/ruby/system/MemoryControl.hh | 3 | ||||
-rw-r--r-- | src/mem/ruby/system/RubyMemoryControl.cc | 19 | ||||
-rw-r--r-- | src/mem/ruby/system/RubyMemoryControl.hh | 3 | ||||
-rw-r--r-- | src/mem/slicc/ast/MachineAST.py | 4 | ||||
-rw-r--r-- | src/mem/slicc/symbols/StateMachine.py | 404 |
9 files changed, 339 insertions, 385 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; diff --git a/src/mem/slicc/ast/MachineAST.py b/src/mem/slicc/ast/MachineAST.py index c48d2aef1..d494cb7ce 100644 --- a/src/mem/slicc/ast/MachineAST.py +++ b/src/mem/slicc/ast/MachineAST.py @@ -44,10 +44,6 @@ class MachineAST(DeclAST): s = set(('%s_Controller.cc' % self.ident, '%s_Controller.hh' % self.ident, '%s_Controller.py' % self.ident, - '%s_Profiler.cc' % self.ident, - '%s_Profiler.hh' % self.ident, - '%s_ProfileDumper.cc' % self.ident, - '%s_ProfileDumper.hh' % self.ident, '%s_Transitions.cc' % self.ident, '%s_Wakeup.cc' % self.ident)) diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index c2ee42553..a110092b6 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -173,10 +173,6 @@ class StateMachine(Symbol): self.printControllerCC(path, includes) self.printCSwitch(path) self.printCWakeup(path, includes) - self.printProfilerCC(path) - self.printProfilerHH(path) - self.printProfileDumperCC(path) - self.printProfileDumperHH(path) def printControllerPython(self, path): code = self.symtab.codeFormatter() @@ -228,8 +224,6 @@ class $py_ident(RubyController): #include <sstream> #include <string> -#include "mem/protocol/${ident}_ProfileDumper.hh" -#include "mem/protocol/${ident}_Profiler.hh" #include "mem/protocol/TransitionResult.hh" #include "mem/protocol/Types.hh" #include "mem/ruby/common/Consumer.hh" @@ -263,10 +257,14 @@ class $c_ident : public AbstractController const std::string toString() const; const std::string getName() const; void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; } + void print(std::ostream& out) const; void wakeup(); void printStats(std::ostream& out) const; void clearStats(); + void regStats(); + void collateStats(); + void blockOnQueue(Address addr, MessageBuffer* port); void unblock(Address addr); void recordCacheTrace(int cntrl, CacheRecorder* tr); @@ -275,6 +273,12 @@ class $c_ident : public AbstractController bool functionalReadBuffers(PacketPtr&); uint32_t functionalWriteBuffers(PacketPtr&); + void countTransition(${ident}_State state, ${ident}_Event event); + void possibleTransition(${ident}_State state, ${ident}_Event event); + uint64 getEventCount(${ident}_Event event); + bool isPossible(${ident}_State state, ${ident}_Event event); + uint64 getTransitionCount(${ident}_State state, ${ident}_Event event); + private: ''') @@ -319,8 +323,12 @@ TransitionResult doTransitionWorker(${ident}_Event event, code(''' const Address& addr); -static ${ident}_ProfileDumper s_profileDumper; -${ident}_Profiler m_profiler; +int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; +int m_event_counters[${ident}_Event_NUM]; +bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; + +static std::vector<Stats::Vector *> eventVec; +static std::vector<std::vector<Stats::Vector *> > transVec; static int m_num_controllers; // Internal functions @@ -440,7 +448,8 @@ ${c_ident}Params::create() } int $c_ident::m_num_controllers = 0; -${ident}_ProfileDumper $c_ident::s_profileDumper; +std::vector<Stats::Vector *> $c_ident::eventVec; +std::vector<std::vector<Stats::Vector *> > $c_ident::transVec; // for adding information to the protocol debug trace stringstream ${ident}_transitionComment; @@ -520,6 +529,16 @@ m_${{var.c_ident}}_ptr->setSender(this); code(''' if (p->peer != NULL) connectWithPeer(p->peer); + +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(''' @@ -528,17 +547,13 @@ if (p->peer != NULL) void $c_ident::init() { - MachineType machine_type; - int base; - machine_type = string_to_MachineType("${{var.machine.ident}}"); - base = MachineType_base_number(machine_type); + MachineType machine_type = string_to_MachineType("${{var.machine.ident}}"); + int base = MachineType_base_number(machine_type); m_machineID.type = MachineType_${ident}; m_machineID.num = m_version; // initialize objects - m_profiler.setVersion(m_version); - s_profileDumper.registerProfiler(&m_profiler); ''') @@ -675,7 +690,7 @@ $vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{v if not stall: state = "%s_State_%s" % (self.ident, trans.state.ident) event = "%s_Event_%s" % (self.ident, trans.event.ident) - code('m_profiler.possibleTransition($state, $event);') + code('possibleTransition($state, $event);') code.dedent() code(''' @@ -701,6 +716,107 @@ $vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{v seq_ident = "m_%s_ptr" % param.name code(''' + +void +$c_ident::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(name() + "." + ${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<Stats::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(name() + "." + ${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) { + std::map<uint32_t, AbstractController *>::iterator it = + g_abs_controls[MachineType_${ident}].find(i); + assert(it != g_abs_controls[MachineType_${ident}].end()); + (*eventVec[event])[i] = + (($c_ident *)(*it).second)->getEventCount(event); + } + } + + for (${ident}_State state = ${ident}_State_FIRST; + state < ${ident}_State_NUM; ++state) { + + for (${ident}_Event event = ${ident}_Event_FIRST; + event < ${ident}_Event_NUM; ++event) { + + for (unsigned int i = 0; i < m_num_controllers; ++i) { + std::map<uint32_t, AbstractController *>::iterator it = + g_abs_controls[MachineType_${ident}].find(i); + assert(it != g_abs_controls[MachineType_${ident}].end()); + (*transVec[state][event])[i] = + (($c_ident *)(*it).second)->getTransitionCount(state, event); + } + } + } +} + +void +$c_ident::countTransition(${ident}_State state, ${ident}_Event event) +{ + assert(m_possible[state][event]); + m_counters[state][event]++; + m_event_counters[event]++; +} +void +$c_ident::possibleTransition(${ident}_State state, + ${ident}_Event event) +{ + m_possible[state][event] = true; +} + +uint64 +$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 +$c_ident::getTransitionCount(${ident}_State state, + ${ident}_Event event) +{ + return m_counters[state][event]; +} + int $c_ident::getNumControllers() { @@ -768,30 +884,25 @@ $c_ident::printStats(ostream& out) const # them. Print out these stats before dumping state transition stats. # for param in self.config_parameters: - if param.type_ast.type.ident == "DirectoryMemory" or \ - param.type_ast.type.ident == "MemoryControl": + if param.type_ast.type.ident == "DirectoryMemory": assert(param.pointer) code(' m_${{param.ident}}_ptr->printStats(out);') code(''' - if (m_version == 0) { - s_profileDumper.dumpStats(out); - } } -void $c_ident::clearStats() { -''') - # - # Cache and Memory Controllers have specific profilers associated with - # them. These stats must be cleared too. - # - for param in self.config_parameters: - if param.type_ast.type.ident == "MemoryControl": - assert(param.pointer) - code(' m_${{param.ident}}_ptr->clearStats();') +void $c_ident::clearStats() +{ + 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; + } - code(''' - m_profiler.clearStats(); AbstractController::clearStats(); } ''') @@ -1130,7 +1241,7 @@ ${ident}_Controller::doTransition(${ident}_Event event, if (result == TransitionResult_Valid) { DPRINTF(RubyGenerated, "next_state: %s\\n", ${ident}_State_to_string(next_state)); - m_profiler.countTransition(state, event); + countTransition(state, event); DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n", curTick(), m_version, "${ident}", ${ident}_Event_to_string(event), @@ -1292,231 +1403,6 @@ if (!checkResourceAvailable(%s_RequestType_%s, addr)) { ''') code.write(path, "%s_Transitions.cc" % self.ident) - def printProfileDumperHH(self, path): - code = self.symtab.codeFormatter() - ident = self.ident - - code(''' -// Auto generated C++ code started by $__file__:$__line__ -// ${ident}: ${{self.short}} - -#ifndef __${ident}_PROFILE_DUMPER_HH__ -#define __${ident}_PROFILE_DUMPER_HH__ - -#include <cassert> -#include <iostream> -#include <vector> - -#include "${ident}_Event.hh" -#include "${ident}_Profiler.hh" - -typedef std::vector<${ident}_Profiler *> ${ident}_profilers; - -class ${ident}_ProfileDumper -{ - public: - ${ident}_ProfileDumper(); - void registerProfiler(${ident}_Profiler* profiler); - void dumpStats(std::ostream& out) const; - - private: - ${ident}_profilers m_profilers; -}; - -#endif // __${ident}_PROFILE_DUMPER_HH__ -''') - code.write(path, "%s_ProfileDumper.hh" % self.ident) - - def printProfileDumperCC(self, path): - code = self.symtab.codeFormatter() - ident = self.ident - - code(''' -// Auto generated C++ code started by $__file__:$__line__ -// ${ident}: ${{self.short}} - -#include "mem/protocol/${ident}_ProfileDumper.hh" - -${ident}_ProfileDumper::${ident}_ProfileDumper() -{ -} - -void -${ident}_ProfileDumper::registerProfiler(${ident}_Profiler* profiler) -{ - if (profiler->getVersion() >= m_profilers.size()) - m_profilers.resize(profiler->getVersion() + 1); - m_profilers[profiler->getVersion()] = profiler; -} - -void -${ident}_ProfileDumper::dumpStats(std::ostream& out) const -{ - out << " --- ${ident} ---\\n"; - out << " - Event Counts -\\n"; - for (${ident}_Event event = ${ident}_Event_FIRST; - event < ${ident}_Event_NUM; - ++event) { - out << (${ident}_Event) event << " ["; - uint64 total = 0; - for (int i = 0; i < m_profilers.size(); i++) { - out << m_profilers[i]->getEventCount(event) << " "; - total += m_profilers[i]->getEventCount(event); - } - out << "] " << total << "\\n"; - } - out << "\\n"; - out << " - Transitions -\\n"; - for (${ident}_State state = ${ident}_State_FIRST; - state < ${ident}_State_NUM; - ++state) { - for (${ident}_Event event = ${ident}_Event_FIRST; - event < ${ident}_Event_NUM; - ++event) { - if (m_profilers[0]->isPossible(state, event)) { - out << (${ident}_State) state << " " - << (${ident}_Event) event << " ["; - uint64 total = 0; - for (int i = 0; i < m_profilers.size(); i++) { - out << m_profilers[i]->getTransitionCount(state, event) << " "; - total += m_profilers[i]->getTransitionCount(state, event); - } - out << "] " << total << "\\n"; - } - } - out << "\\n"; - } -} -''') - code.write(path, "%s_ProfileDumper.cc" % self.ident) - - def printProfilerHH(self, path): - code = self.symtab.codeFormatter() - ident = self.ident - - code(''' -// Auto generated C++ code started by $__file__:$__line__ -// ${ident}: ${{self.short}} - -#ifndef __${ident}_PROFILER_HH__ -#define __${ident}_PROFILER_HH__ - -#include <cassert> -#include <iostream> - -#include "mem/protocol/${ident}_Event.hh" -#include "mem/protocol/${ident}_State.hh" -#include "mem/ruby/common/TypeDefines.hh" - -class ${ident}_Profiler -{ - public: - ${ident}_Profiler(); - void setVersion(int version); - int getVersion(); - void countTransition(${ident}_State state, ${ident}_Event event); - void possibleTransition(${ident}_State state, ${ident}_Event event); - uint64 getEventCount(${ident}_Event event); - bool isPossible(${ident}_State state, ${ident}_Event event); - uint64 getTransitionCount(${ident}_State state, ${ident}_Event event); - void clearStats(); - - private: - int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; - int m_event_counters[${ident}_Event_NUM]; - bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; - int m_version; -}; - -#endif // __${ident}_PROFILER_HH__ -''') - code.write(path, "%s_Profiler.hh" % self.ident) - - def printProfilerCC(self, path): - code = self.symtab.codeFormatter() - ident = self.ident - - code(''' -// Auto generated C++ code started by $__file__:$__line__ -// ${ident}: ${{self.short}} - -#include <cassert> - -#include "mem/protocol/${ident}_Profiler.hh" - -${ident}_Profiler::${ident}_Profiler() -{ - 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; - } -} - -void -${ident}_Profiler::setVersion(int version) -{ - m_version = version; -} - -int -${ident}_Profiler::getVersion() -{ - return m_version; -} - -void -${ident}_Profiler::clearStats() -{ - 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; - } -} -void -${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event) -{ - assert(m_possible[state][event]); - m_counters[state][event]++; - m_event_counters[event]++; -} -void -${ident}_Profiler::possibleTransition(${ident}_State state, - ${ident}_Event event) -{ - m_possible[state][event] = true; -} - -uint64 -${ident}_Profiler::getEventCount(${ident}_Event event) -{ - return m_event_counters[event]; -} - -bool -${ident}_Profiler::isPossible(${ident}_State state, ${ident}_Event event) -{ - return m_possible[state][event]; -} - -uint64 -${ident}_Profiler::getTransitionCount(${ident}_State state, - ${ident}_Event event) -{ - return m_counters[state][event]; -} - -''') - code.write(path, "%s_Profiler.cc" % self.ident) # ************************** # ******* HTML Files ******* |