diff options
28 files changed, 392 insertions, 533 deletions
diff --git a/src/base/statistics.hh b/src/base/statistics.hh index f3b6ae39f..dd3cf5e9c 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -331,6 +331,12 @@ class DataWrapVec : public DataWrap<Derived, InfoProxyType> public: typedef InfoProxyType<Derived> Info; + DataWrapVec() + {} + + DataWrapVec(const DataWrapVec &ref) + {} + // The following functions are specific to vectors. If you use them // in a non vector context, you will get a nice compiler error! diff --git a/src/mem/ruby/network/Network.cc b/src/mem/ruby/network/Network.cc index d39e6e1e8..5e44c435e 100644 --- a/src/mem/ruby/network/Network.cc +++ b/src/mem/ruby/network/Network.cc @@ -59,6 +59,9 @@ Network::Network(const Params *p) AbstractController *abs_cntrl = ext_link->params()->ext_node; abs_cntrl->initNetworkPtr(this); } + + // Register a callback function for combining the statistics + Stats::registerDumpCallback(new StatsCallback(this)); } void diff --git a/src/mem/ruby/network/Network.hh b/src/mem/ruby/network/Network.hh index 400972020..33a3fc33f 100644 --- a/src/mem/ruby/network/Network.hh +++ b/src/mem/ruby/network/Network.hh @@ -88,8 +88,7 @@ class Network : public ClockedObject LinkDirection direction, const NetDest& routing_table_entry) = 0; - virtual void printStats(std::ostream& out) const = 0; - virtual void clearStats() = 0; + virtual void collateStats() = 0; virtual void print(std::ostream& out) const = 0; /* @@ -107,13 +106,30 @@ class Network : public ClockedObject Network(const Network& obj); Network& operator=(const Network& obj); - protected: - const std::string m_name; - int m_nodes; + uint32_t m_nodes; static uint32_t m_virtual_networks; Topology* m_topology_ptr; static uint32_t m_control_msg_size; static uint32_t m_data_msg_size; + + private: + //! Callback class used for collating statistics from all the + //! controller of this type. + class StatsCallback : public Callback + { + private: + Network *ctr; + + public: + virtual ~StatsCallback() {} + + StatsCallback(Network *_ctr) + : ctr(_ctr) + { + } + + void process() {ctr->collateStats();} + }; }; inline std::ostream& diff --git a/src/mem/ruby/network/garnet/BaseGarnetNetwork.cc b/src/mem/ruby/network/garnet/BaseGarnetNetwork.cc index 3e70900dc..1082a15fb 100644 --- a/src/mem/ruby/network/garnet/BaseGarnetNetwork.cc +++ b/src/mem/ruby/network/garnet/BaseGarnetNetwork.cc @@ -71,17 +71,9 @@ BaseGarnetNetwork::BaseGarnetNetwork(const Params *p) m_in_use.resize(m_virtual_networks); m_ordered.resize(m_virtual_networks); - m_flits_received.resize(m_virtual_networks); - m_flits_injected.resize(m_virtual_networks); - m_network_latency.resize(m_virtual_networks); - m_queueing_latency.resize(m_virtual_networks); for (int i = 0; i < m_virtual_networks; i++) { m_in_use[i] = false; m_ordered[i] = false; - m_flits_received[i] = 0; - m_flits_injected[i] = 0; - m_network_latency[i] = 0.0; - m_queueing_latency[i] = 0.0; } for (int node = 0; node < m_nodes; node++) { @@ -121,60 +113,55 @@ BaseGarnetNetwork::getFromNetQueue(NodeID id, bool ordered, int network_num, } void -BaseGarnetNetwork::clearStats() +BaseGarnetNetwork::regStats() { -} - -void -BaseGarnetNetwork::printStats(ostream& out) const -{ - out << endl; - out << "Network Stats" << endl; - out << "-------------" << endl; - out << endl; - printPerformanceStats(out); - printLinkStats(out); - printPowerStats(out); -} - -void -BaseGarnetNetwork::printPerformanceStats(ostream& out) const -{ - int total_flits_injected = 0; - int total_flits_received = 0; - int total_network_latency = 0.0; - int total_queueing_latency = 0.0; + m_flits_received + .init(m_virtual_networks) + .name(name() + ".flits_received") + .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline) + ; + + m_flits_injected + .init(m_virtual_networks) + .name(name() + ".flits_injected") + .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline) + ; + + m_network_latency + .init(m_virtual_networks) + .name(name() + ".network_latency") + .flags(Stats::oneline) + ; + + m_queueing_latency + .init(m_virtual_networks) + .name(name() + ".queueing_latency") + .flags(Stats::oneline) + ; for (int i = 0; i < m_virtual_networks; i++) { - if (!m_in_use[i]) - continue; - - out << "[Vnet " << i << "]: flits injected = " - << m_flits_injected[i] << endl; - out << "[Vnet " << i << "]: flits received = " - << m_flits_received[i] << endl; - out << "[Vnet " << i << "]: average network latency = " - << ((double) m_network_latency[i] / (double) m_flits_received[i]) - << endl; - out << "[Vnet " << i << "]: average queueing (at source NI) latency = " - << ((double) m_queueing_latency[i] / (double) m_flits_received[i]) - << endl; - - out << endl; - total_flits_injected += m_flits_injected[i]; - total_flits_received += m_flits_received[i]; - total_network_latency += m_network_latency[i]; - total_queueing_latency += m_queueing_latency[i]; + m_flits_received.subname(i, csprintf("vnet-%i", i)); + m_flits_injected.subname(i, csprintf("vnet-%i", i)); + m_network_latency.subname(i, csprintf("vnet-%i", i)); + m_queueing_latency.subname(i, csprintf("vnet-%i", i)); } - out << "Total flits injected = " << total_flits_injected << endl; - out << "Total flits received = " << total_flits_received << endl; - out << "Average network latency = " - << ((double) total_network_latency/ (double) total_flits_received) << endl; - out << "Average queueing (at source NI) latency = " - << ((double) total_queueing_latency/ (double) total_flits_received) << endl; - out << "Average latency = " - << ((double) (total_queueing_latency + total_network_latency) / - (double) total_flits_received)<< endl; - out << "-------------" << endl; - out << endl; + + m_avg_vnet_latency + .name(name() + ".average_vnet_latency") + .flags(Stats::oneline); + m_avg_vnet_latency = m_network_latency / m_flits_received; + + m_avg_vqueue_latency + .name(name() + ".average_vqueue_latency") + .flags(Stats::oneline); + m_avg_vqueue_latency = m_queueing_latency / m_flits_received; + + m_avg_network_latency.name(name() + ".average_network_latency"); + m_avg_network_latency = sum(m_network_latency) / sum(m_flits_received); + + m_avg_queueing_latency.name(name() + ".average_queueing_latency"); + m_avg_queueing_latency = sum(m_queueing_latency) / sum(m_flits_received); + + m_avg_latency.name(name() + ".average_latency"); + m_avg_latency = m_avg_network_latency + m_avg_queueing_latency; } diff --git a/src/mem/ruby/network/garnet/BaseGarnetNetwork.hh b/src/mem/ruby/network/garnet/BaseGarnetNetwork.hh index b9f86df59..57d4cc581 100644 --- a/src/mem/ruby/network/garnet/BaseGarnetNetwork.hh +++ b/src/mem/ruby/network/garnet/BaseGarnetNetwork.hh @@ -80,27 +80,31 @@ class BaseGarnetNetwork : public Network virtual void checkNetworkAllocation(NodeID id, bool ordered, int network_num, std::string vnet_type) = 0; - void clearStats(); - void printStats(std::ostream& out) const; - void printPerformanceStats(std::ostream& out) const; - virtual void printLinkStats(std::ostream& out) const = 0; - virtual void printPowerStats(std::ostream& out) const = 0; + virtual void regStats(); + virtual void collateStats() {} protected: int m_ni_flit_size; int m_vcs_per_vnet; bool m_enable_fault_model; - std::vector<int> m_flits_received; - std::vector<int> m_flits_injected; - std::vector<double> m_network_latency; - std::vector<double> m_queueing_latency; - std::vector<bool> m_in_use; std::vector<bool> m_ordered; std::vector<std::vector<MessageBuffer*> > m_toNetQueues; std::vector<std::vector<MessageBuffer*> > m_fromNetQueues; + + // Statistical variables + Stats::Vector m_flits_received; + Stats::Vector m_flits_injected; + Stats::Vector m_network_latency; + Stats::Vector m_queueing_latency; + + Stats::Formula m_avg_vnet_latency; + Stats::Formula m_avg_vqueue_latency; + Stats::Formula m_avg_network_latency; + Stats::Formula m_avg_queueing_latency; + Stats::Formula m_avg_latency; }; #endif // __MEM_RUBY_NETWORK_GARNET_BASEGARNETNETWORK_HH__ diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc b/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc index 238006881..8db57267e 100644 --- a/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc +++ b/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc @@ -221,81 +221,82 @@ GarnetNetwork_d::checkNetworkAllocation(NodeID id, bool ordered, } void -GarnetNetwork_d::printLinkStats(ostream& out) const +GarnetNetwork_d::regStats() { - double average_link_utilization = 0; - vector<double> average_vc_load; - average_vc_load.resize(m_virtual_networks*m_vcs_per_vnet); + BaseGarnetNetwork::regStats(); + regLinkStats(); + regPowerStats(); +} - for (int i = 0; i < m_virtual_networks*m_vcs_per_vnet; i++) { - average_vc_load[i] = 0; - } +void +GarnetNetwork_d::regLinkStats() +{ + m_average_link_utilization.name(name() + ".avg_link_utilization"); + + m_average_vc_load + .init(m_virtual_networks * m_vcs_per_vnet) + .name(name() + ".avg_vc_load") + .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline) + ; +} + +void +GarnetNetwork_d::regPowerStats() +{ + m_dynamic_link_power.name(name() + ".link_dynamic_power"); + m_static_link_power.name(name() + ".link_static_power"); + + m_total_link_power.name(name() + ".link_total_power"); + m_total_link_power = m_dynamic_link_power + m_static_link_power; + + m_dynamic_router_power.name(name() + ".router_dynamic_power"); + m_static_router_power.name(name() + ".router_static_power"); + m_clk_power.name(name() + ".clk_power"); + + m_total_router_power.name(name() + ".router_total_power"); + m_total_router_power = m_dynamic_router_power + + m_static_router_power + + m_clk_power; +} + +void +GarnetNetwork_d::collateStats() +{ + collateLinkStats(); + collatePowerStats(); +} - out << endl; +void +GarnetNetwork_d::collateLinkStats() +{ for (int i = 0; i < m_links.size(); i++) { - average_link_utilization += + m_average_link_utilization += (double(m_links[i]->getLinkUtilization())) / (double(curCycle() - g_ruby_start)); - vector<int> vc_load = m_links[i]->getVcLoad(); + vector<unsigned int> vc_load = m_links[i]->getVcLoad(); for (int j = 0; j < vc_load.size(); j++) { - assert(vc_load.size() == m_vcs_per_vnet*m_virtual_networks); - average_vc_load[j] += vc_load[j]; + m_average_vc_load[j] += + ((double)vc_load[j] / (double)(curCycle() - g_ruby_start)); } } - average_link_utilization = - average_link_utilization/m_links.size(); - out << "Average Link Utilization :: " << average_link_utilization - << " flits/cycle" << endl; - out << "-------------" << endl; - - for (int i = 0; i < m_vcs_per_vnet*m_virtual_networks; i++) { - if (!m_in_use[i/m_vcs_per_vnet]) - continue; - - average_vc_load[i] = (double(average_vc_load[i])) / - (double(curCycle() - g_ruby_start)); - out << "Average VC Load [" << i << "] = " << average_vc_load[i] - << " flits/cycle " << endl; - } - out << "-------------" << endl; - out << endl; } void -GarnetNetwork_d::printPowerStats(ostream& out) const +GarnetNetwork_d::collatePowerStats() { - out << "Network Power" << endl; - out << "-------------" << endl; - double m_total_link_power = 0.0; - double m_dynamic_link_power = 0.0; - double m_static_link_power = 0.0; - double m_total_router_power = 0.0; - double m_dynamic_router_power = 0.0; - double m_static_router_power = 0.0; - double m_clk_power = 0.0; - for (int i = 0; i < m_links.size(); i++) { - m_total_link_power += m_links[i]->calculate_power(); + m_links[i]->calculate_power(); m_dynamic_link_power += m_links[i]->get_dynamic_power(); m_static_link_power += m_links[i]->get_static_power(); } for (int i = 0; i < m_routers.size(); i++) { - m_total_router_power += m_routers[i]->calculate_power(); + m_routers[i]->calculate_power(); m_dynamic_router_power += m_routers[i]->get_dynamic_power(); m_static_router_power += m_routers[i]->get_static_power(); m_clk_power += m_routers[i]->get_clk_power(); } - out << "Link Dynamic Power = " << m_dynamic_link_power << " W" << endl; - out << "Link Static Power = " << m_static_link_power << " W" << endl; - out << "Total Link Power = " << m_total_link_power << " W " << endl; - out << "Router Dynamic Power = " << m_dynamic_router_power << " W" << endl; - out << "Router Clock Power = " << m_clk_power << " W" << endl; - out << "Router Static Power = " << m_static_router_power << " W" << endl; - out << "Total Router Power = " << m_total_router_power << " W " <<endl; - out << "-------------" << endl; - out << endl; } void diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.hh b/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.hh index 919e6703e..53cf595e5 100644 --- a/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.hh +++ b/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.hh @@ -63,8 +63,8 @@ class GarnetNetwork_d : public BaseGarnetNetwork int getBuffersPerDataVC() {return m_buffers_per_data_vc; } int getBuffersPerCtrlVC() {return m_buffers_per_ctrl_vc; } - void printLinkStats(std::ostream& out) const; - void printPowerStats(std::ostream& out) const; + void collateStats(); + void regStats(); void print(std::ostream& out) const; VNET_type @@ -96,6 +96,11 @@ class GarnetNetwork_d : public BaseGarnetNetwork GarnetNetwork_d(const GarnetNetwork_d& obj); GarnetNetwork_d& operator=(const GarnetNetwork_d& obj); + void collateLinkStats(); + void collatePowerStats(); + void regLinkStats(); + void regPowerStats(); + std::vector<VNET_type > m_vnet_type; std::vector<Router_d *> m_routers; // All Routers in Network @@ -105,6 +110,20 @@ class GarnetNetwork_d : public BaseGarnetNetwork int m_buffers_per_data_vc; int m_buffers_per_ctrl_vc; + + // Statistical variables for power + Stats::Scalar m_dynamic_link_power; + Stats::Scalar m_static_link_power; + Stats::Formula m_total_link_power; + + Stats::Scalar m_dynamic_router_power; + Stats::Scalar m_static_router_power; + Stats::Scalar m_clk_power; + Stats::Formula m_total_router_power; + + // Statistical variables for performance + Stats::Scalar m_average_link_utilization; + Stats::Vector m_average_vc_load; }; inline std::ostream& diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/InputUnit_d.hh b/src/mem/ruby/network/garnet/fixed-pipeline/InputUnit_d.hh index 6afb4726b..2c37996b3 100644 --- a/src/mem/ruby/network/garnet/fixed-pipeline/InputUnit_d.hh +++ b/src/mem/ruby/network/garnet/fixed-pipeline/InputUnit_d.hh @@ -161,17 +161,10 @@ class InputUnit_d : public Consumer m_credit_link = credit_link; } - inline double - get_buf_read_count(int vnet) - { - return m_num_buffer_reads[vnet]; - } - - inline double - get_buf_write_count(int vnet) - { - return m_num_buffer_writes[vnet]; - } + double get_buf_read_count(unsigned int vnet) const + { return m_num_buffer_reads[vnet]; } + double get_buf_write_count(unsigned int vnet) const + { return m_num_buffer_writes[vnet]; } uint32_t functionalWrite(Packet *pkt); @@ -179,8 +172,6 @@ class InputUnit_d : public Consumer int m_id; int m_num_vcs; int m_vc_per_vnet; - std::vector<double> m_num_buffer_writes; - std::vector<double> m_num_buffer_reads; Router_d *m_router; NetworkLink_d *m_in_link; @@ -189,6 +180,10 @@ class InputUnit_d : public Consumer // Virtual channels std::vector<VirtualChannel_d *> m_vcs; + + // Statistical variables + std::vector<double> m_num_buffer_writes; + std::vector<double> m_num_buffer_reads; }; #endif // __MEM_RUBY_NETWORK_GARNET_FIXED_PIPELINE_INPUT_UNIT_D_HH__ diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.cc b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.cc index d84bf8e69..32fce83ce 100644 --- a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.cc +++ b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.cc @@ -76,18 +76,6 @@ NetworkLink_d::wakeup() } } -std::vector<int> -NetworkLink_d::getVcLoad() -{ - return m_vc_load; -} - -int -NetworkLink_d::getLinkUtilization() -{ - return m_link_utilized; -} - NetworkLink_d * NetworkLink_dParams::create() { diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.hh b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.hh index 9e149392e..fcdd28b67 100644 --- a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.hh +++ b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.hh @@ -53,14 +53,15 @@ class NetworkLink_d : public ClockedObject, public Consumer void setLinkConsumer(Consumer *consumer); void setSourceQueue(flitBuffer_d *srcQueue); void print(std::ostream& out) const{} - int getLinkUtilization(); - std::vector<int> getVcLoad(); int get_id(){return m_id;} - double get_dynamic_power(){return m_power_dyn;} - double get_static_power(){return m_power_sta;} void wakeup(); - double calculate_power(); + void calculate_power(); + double get_dynamic_power() const { return m_power_dyn; } + double get_static_power()const { return m_power_sta; } + + unsigned int getLinkUtilization() const { return m_link_utilized; } + const std::vector<unsigned int> & getVcLoad() const { return m_vc_load; } inline bool isReady(Cycles curTime) { return linkBuffer->isReady(curTime); } @@ -71,7 +72,7 @@ class NetworkLink_d : public ClockedObject, public Consumer void init_net_ptr(GarnetNetwork_d* net_ptr) { m_net_ptr = net_ptr; } uint32_t functionalWrite(Packet *); - protected: + private: int m_id; Cycles m_latency; int channel_width; @@ -80,10 +81,12 @@ class NetworkLink_d : public ClockedObject, public Consumer flitBuffer_d *linkBuffer; Consumer *link_consumer; flitBuffer_d *link_srcQueue; - int m_link_utilized; - std::vector<int> m_vc_load; int m_flit_width; + // Statistical variables + unsigned int m_link_utilized; + std::vector<unsigned int> m_vc_load; + double m_power_dyn; double m_power_sta; }; diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/Router_d.cc b/src/mem/ruby/network/garnet/fixed-pipeline/Router_d.cc index fd4ce5389..3370c356c 100644 --- a/src/mem/ruby/network/garnet/fixed-pipeline/Router_d.cc +++ b/src/mem/ruby/network/garnet/fixed-pipeline/Router_d.cc @@ -186,7 +186,7 @@ Router_d::printFaultVector(ostream& out) for (int fault_type_index = 0; fault_type_index < num_fault_types; fault_type_index++){ out << " - probability of ("; - out << + out << m_network_ptr->fault_model->fault_type_to_string(fault_type_index); out << ") = "; out << fault_vector[fault_type_index] << endl; @@ -198,7 +198,7 @@ Router_d::printAggregateFaultProbability(std::ostream& out) { int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS; float aggregate_fault_prob; - get_aggregate_fault_probability(temperature_celcius, + get_aggregate_fault_probability(temperature_celcius, &aggregate_fault_prob); out << "Router-" << m_id << " fault probability: "; out << aggregate_fault_prob << endl; diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/Router_d.hh b/src/mem/ruby/network/garnet/fixed-pipeline/Router_d.hh index 4aa437c9c..17ba54fa5 100644 --- a/src/mem/ruby/network/garnet/fixed-pipeline/Router_d.hh +++ b/src/mem/ruby/network/garnet/fixed-pipeline/Router_d.hh @@ -89,12 +89,12 @@ class Router_d : public BasicRouter void printFaultVector(std::ostream& out); void printAggregateFaultProbability(std::ostream& out); - double calculate_power(); + void calculate_power(); void calculate_performance_numbers(); + double get_dynamic_power() const { return m_power_dyn; } + double get_static_power() const { return m_power_sta; } + double get_clk_power() const { return m_clk_power; } - double get_dynamic_power(){return m_power_dyn;} - double get_static_power(){return m_power_sta;} - double get_clk_power(){return m_clk_power;} bool get_fault_vector(int temperature, float fault_vector[]){ return m_network_ptr->fault_model->fault_vector(m_id, temperature, fault_vector); @@ -110,11 +110,6 @@ class Router_d : public BasicRouter private: int m_virtual_networks, m_num_vcs, m_vc_per_vnet; GarnetNetwork_d *m_network_ptr; - - std::vector<double> buf_read_count; - std::vector<double> buf_write_count; - std::vector<double> vc_local_arbit_count; - std::vector<double> vc_global_arbit_count; double sw_local_arbit_count, sw_global_arbit_count; double crossbar_count; @@ -125,9 +120,16 @@ class Router_d : public BasicRouter SWallocator_d *m_sw_alloc; Switch_d *m_switch; + // Statistical variables for power double m_power_dyn; double m_power_sta; double m_clk_power; + + // Statistical variables for performance + std::vector<double> buf_read_count; + std::vector<double> buf_write_count; + std::vector<double> vc_local_arbit_count; + std::vector<double> vc_global_arbit_count; }; #endif // __MEM_RUBY_NETWORK_GARNET_FIXED_PIPELINE_ROUTER_D_HH__ diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/VCallocator_d.hh b/src/mem/ruby/network/garnet/fixed-pipeline/VCallocator_d.hh index d28c6f82f..246b7ad2f 100644 --- a/src/mem/ruby/network/garnet/fixed-pipeline/VCallocator_d.hh +++ b/src/mem/ruby/network/garnet/fixed-pipeline/VCallocator_d.hh @@ -57,26 +57,17 @@ class VCallocator_d : public Consumer bool is_invc_candidate(int inport_iter, int invc_iter); void select_outvc(int inport_iter, int invc_iter); - inline double - get_local_arbit_count(int vnet) - { - return m_local_arbiter_activity[vnet]; - } - - inline double - get_global_arbit_count(int vnet) - { - return m_global_arbiter_activity[vnet]; - } + double get_local_arbit_count(unsigned int vnet) const + { return m_local_arbiter_activity[vnet]; } + + double get_global_arbit_count(unsigned int vnet) const + { return m_global_arbiter_activity[vnet]; } private: int m_num_vcs, m_vc_per_vnet; int m_num_inports; int m_num_outports; - std::vector<double > m_local_arbiter_activity; - std::vector<double > m_global_arbiter_activity; - Router_d *m_router; // First stage of arbitration @@ -94,6 +85,10 @@ class VCallocator_d : public Consumer std::vector<InputUnit_d *> m_input_unit; std::vector<OutputUnit_d *> m_output_unit; + + // Statistical variables + std::vector<double> m_local_arbiter_activity; + std::vector<double> m_global_arbiter_activity; }; #endif // __MEM_RUBY_NETWORK_GARNET_FIXED_PIPELINE_VC_ALLOCATOR_D_HH__ diff --git a/src/mem/ruby/network/garnet/flexible-pipeline/GarnetNetwork.cc b/src/mem/ruby/network/garnet/flexible-pipeline/GarnetNetwork.cc index ea08a054b..1e24cbc69 100644 --- a/src/mem/ruby/network/garnet/flexible-pipeline/GarnetNetwork.cc +++ b/src/mem/ruby/network/garnet/flexible-pipeline/GarnetNetwork.cc @@ -210,54 +210,38 @@ GarnetNetwork::functionalWrite(Packet *pkt) } void -GarnetNetwork::printLinkStats(ostream& out) const +GarnetNetwork::regStats() { - double average_link_utilization = 0; - vector<double> average_vc_load; - average_vc_load.resize(m_virtual_networks*m_vcs_per_vnet); - - for (int i = 0; i < m_virtual_networks*m_vcs_per_vnet; i++) { - average_vc_load[i] = 0; + BaseGarnetNetwork::regStats(); + + m_average_link_utilization.name(name() + ".avg_link_utilization"); + + m_average_vc_load + .init(m_virtual_networks * m_vcs_per_vnet) + .name(name() + ".avg_vc_load") + .flags(Stats::pdf | Stats::total | Stats::nozero) + ; + for (int i = 0; i < m_virtual_networks * m_vcs_per_vnet; i++) { + m_average_vc_load + .subname(i, csprintf(".%i", i)) + .flags(Stats::nozero) + ; } +} - out << endl; +void +GarnetNetwork::collateStats() +{ for (int i = 0; i < m_links.size(); i++) { - average_link_utilization += + m_average_link_utilization += (double(m_links[i]->getLinkUtilization())) / (double(curCycle() - g_ruby_start)); - vector<int> vc_load = m_links[i]->getVcLoad(); + vector<unsigned int> vc_load = m_links[i]->getVcLoad(); for (int j = 0; j < vc_load.size(); j++) { - assert(vc_load.size() == m_vcs_per_vnet*m_virtual_networks); - average_vc_load[j] += vc_load[j]; + m_average_vc_load[j] += vc_load[j]; } } - average_link_utilization = - average_link_utilization/m_links.size(); - out << "Average Link Utilization :: " << average_link_utilization - << " flits/cycle" << endl; - out << "-------------" << endl; - - for (int i = 0; i < m_vcs_per_vnet*m_virtual_networks; i++) { - if (!m_in_use[i/m_vcs_per_vnet]) - continue; - - average_vc_load[i] = double(average_vc_load[i]) / - (double(curCycle() - g_ruby_start)); - out << "Average VC Load [" << i << "] = " << average_vc_load[i] - << " flits/cycle " << endl; - } - out << "-------------" << endl; - out << endl; -} - -void -GarnetNetwork::printPowerStats(ostream& out) const -{ - out << "Network Power" << endl; - out << "-------------" << endl; - out << "Orion does not work with flexible pipeline" << endl; - out << endl; } void diff --git a/src/mem/ruby/network/garnet/flexible-pipeline/GarnetNetwork.hh b/src/mem/ruby/network/garnet/flexible-pipeline/GarnetNetwork.hh index fb4f99d19..d468e9614 100644 --- a/src/mem/ruby/network/garnet/flexible-pipeline/GarnetNetwork.hh +++ b/src/mem/ruby/network/garnet/flexible-pipeline/GarnetNetwork.hh @@ -58,11 +58,10 @@ class GarnetNetwork : public BaseGarnetNetwork int getBufferSize() { return m_buffer_size; } int getNumPipeStages() {return m_number_of_pipe_stages; } - int getNumNodes(){ return m_nodes; } - void printLinkStats(std::ostream& out) const; - void printPowerStats(std::ostream& out) const; + void collateStats(); + void regStats(); void print(std::ostream& out) const; // Methods used by Topology to setup the network @@ -97,6 +96,10 @@ class GarnetNetwork : public BaseGarnetNetwork int m_buffer_size; int m_number_of_pipe_stages; + + // Statistical variables + Stats::Scalar m_average_link_utilization; + Stats::Vector m_average_vc_load; }; inline std::ostream& diff --git a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.cc b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.cc index 9881d8063..04e8a9da9 100644 --- a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.cc +++ b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.cc @@ -40,6 +40,7 @@ NetworkLink::NetworkLink(const Params *p) m_link_utilized = 0; m_latency = p->link_latency; m_id = p->link_id; + int num_net = p->virt_nets; int num_vc = p->vcs_per_vnet; m_vc_load.resize(num_net * num_vc); @@ -53,12 +54,6 @@ NetworkLink::~NetworkLink() delete linkBuffer; } -int -NetworkLink::get_id() -{ - return m_id; -} - void NetworkLink::setLinkConsumer(FlexibleConsumer *consumer) { @@ -101,18 +96,6 @@ NetworkLink::release_vc_link(int vc, Cycles release_time) link_source->release_vc(m_out_port, vc, release_time); } -std::vector<int> -NetworkLink::getVcLoad() -{ - return m_vc_load; -} - -double -NetworkLink::getLinkUtilization() -{ - return (double(m_link_utilized)); -} - bool NetworkLink::isReady() { diff --git a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh index 7003114a1..9b8a9bc47 100644 --- a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh +++ b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh @@ -59,7 +59,7 @@ class NetworkLink : public ClockedObject, public FlexibleConsumer bool is_vc_ready(flit *t_flit); - int get_id(); + int get_id() const { return m_id; } void setInPort(int port); void setOutPort(int port); void wakeup(); @@ -69,29 +69,28 @@ class NetworkLink : public ClockedObject, public FlexibleConsumer void request_vc_link(int vc, NetDest destination, Cycles request_time); bool isBufferNotFull_link(int vc); void setSource(FlexibleConsumer *source); - double getLinkUtilization(); - std::vector<int> getVcLoad(); + void init_net_ptr(GarnetNetwork* net_ptr) { m_net_ptr = net_ptr; } - void init_net_ptr(GarnetNetwork* net_ptr) - { - m_net_ptr = net_ptr; - } + unsigned int getLinkUtilization() const { return m_link_utilized; } + const std::vector<unsigned int> & getVcLoad() const { return m_vc_load; } bool functionalRead(Packet *); uint32_t functionalWrite(Packet *); - protected: + private: int m_id; Cycles m_latency; int m_in_port, m_out_port; - int m_link_utilized; - std::vector<int> m_vc_load; GarnetNetwork *m_net_ptr; flitBuffer *linkBuffer; FlexibleConsumer *link_consumer; FlexibleConsumer *link_source; flitBuffer *link_srcQueue; + + // Statistical variables + unsigned int m_link_utilized; + std::vector<unsigned int> m_vc_load; }; #endif // __MEM_RUBY_NETWORK_GARNET_FLEXIBLE_PIPELINE_NETWORK_LINK_HH__ diff --git a/src/mem/ruby/network/orion/NetworkPower.cc b/src/mem/ruby/network/orion/NetworkPower.cc index c58d64a17..f4a471986 100644 --- a/src/mem/ruby/network/orion/NetworkPower.cc +++ b/src/mem/ruby/network/orion/NetworkPower.cc @@ -34,7 +34,7 @@ #include "mem/ruby/network/orion/OrionLink.hh" #include "mem/ruby/network/orion/OrionRouter.hh" -double +void Router_d::calculate_power() { //Network Activities from garnet @@ -97,7 +97,7 @@ Router_d::calculate_power() uint32_t in_buf_per_data_vc = m_network_ptr->getBuffersPerDataVC(); uint32_t in_buf_per_ctrl_vc = m_network_ptr->getBuffersPerCtrlVC(); //flit width in bits - uint32_t flit_width_bits = m_network_ptr->getNiFlitSize() * 8; + uint32_t flit_width_bits = m_network_ptr->getNiFlitSize() * 8; orion_rtr_ptr = new OrionRouter( num_in_port, @@ -120,16 +120,11 @@ Router_d::calculate_power() double Psw_arb_local_dyn = 0.0; double Psw_arb_global_dyn = 0.0; double Pxbar_dyn = 0.0; - double Ptotal_dyn = 0.0; double Pbuf_sta = 0.0; double Pvc_arb_sta = 0.0; double Psw_arb_sta = 0.0; double Pxbar_sta = 0.0; - double Ptotal_sta = 0.0; - - double Ptotal = 0.0; - //Dynamic Power @@ -198,13 +193,11 @@ Router_d::calculate_power() (crossbar_count/sim_cycles)*freq_Hz; // Total - Ptotal_dyn = Pbuf_wr_dyn + Pbuf_rd_dyn + - Pvc_arb_local_dyn + Pvc_arb_global_dyn + - Psw_arb_local_dyn + Psw_arb_global_dyn + - Pxbar_dyn; + m_power_dyn = Pbuf_wr_dyn + Pbuf_rd_dyn + + Pvc_arb_local_dyn + Pvc_arb_global_dyn + + Psw_arb_local_dyn + Psw_arb_global_dyn + + Pxbar_dyn; - m_power_dyn = Ptotal_dyn; - // Clock Power m_clk_power = orion_rtr_ptr->calc_dynamic_energy_clock()*freq_Hz; @@ -214,16 +207,10 @@ Router_d::calculate_power() Psw_arb_sta = orion_rtr_ptr->get_static_power_sa(); Pxbar_sta = orion_rtr_ptr->get_static_power_xbar(); - Ptotal_sta += Pbuf_sta + Pvc_arb_sta + Psw_arb_sta + Pxbar_sta; - - m_power_sta = Ptotal_sta; - - Ptotal = m_power_dyn + m_power_sta + m_clk_power; - - return Ptotal; + m_power_sta = Pbuf_sta + Pvc_arb_sta + Psw_arb_sta + Pxbar_sta; } -double +void NetworkLink_d::calculate_power() { OrionConfig* orion_cfg_ptr; @@ -249,20 +236,17 @@ NetworkLink_d::calculate_power() // Dynamic Power // Assume half the bits flipped on every link activity - double Plink_dyn = - orion_link_ptr->calc_dynamic_energy(channel_width_bits/2)* - (m_link_utilized/ sim_cycles)*freq_Hz; + double link_dynamic_energy = + orion_link_ptr->calc_dynamic_energy(channel_width_bits/2); + m_power_dyn = link_dynamic_energy * (m_link_utilized / sim_cycles) * + freq_Hz; - m_power_dyn = Plink_dyn; // Static Power // Calculates number of repeaters needed in link, and their static power // For short links, like 1mm, no repeaters are needed so static power is 0 - double Plink_sta = orion_link_ptr->get_static_power(); - - m_power_sta = Plink_sta; - - double Ptotal = m_power_dyn + m_power_sta; + m_power_sta = orion_link_ptr->get_static_power(); - return Ptotal; + delete orion_link_ptr; + delete orion_cfg_ptr; } diff --git a/src/mem/ruby/network/simple/PerfectSwitch.cc b/src/mem/ruby/network/simple/PerfectSwitch.cc index ecfe12f15..d2f05e1b0 100644 --- a/src/mem/ruby/network/simple/PerfectSwitch.cc +++ b/src/mem/ruby/network/simple/PerfectSwitch.cc @@ -102,34 +102,6 @@ PerfectSwitch::addOutPort(const vector<MessageBuffer*>& out, m_routing_table.push_back(routing_table_entry); } -void -PerfectSwitch::clearRoutingTables() -{ - m_routing_table.clear(); -} - -void -PerfectSwitch::clearBuffers() -{ - for (int i = 0; i < m_in.size(); i++){ - for(int vnet = 0; vnet < m_virtual_networks; vnet++) { - m_in[i][vnet]->clear(); - } - } - - for (int i = 0; i < m_out.size(); i++){ - for(int vnet = 0; vnet < m_virtual_networks; vnet++) { - m_out[i][vnet]->clear(); - } - } -} - -void -PerfectSwitch::reconfigureOutPort(const NetDest& routing_table_entry) -{ - m_routing_table.push_back(routing_table_entry); -} - PerfectSwitch::~PerfectSwitch() { } @@ -329,16 +301,15 @@ PerfectSwitch::storeEventInfo(int info) } void -PerfectSwitch::printStats(std::ostream& out) const +PerfectSwitch::clearStats() { - out << "PerfectSwitch printStats" << endl; } - void -PerfectSwitch::clearStats() +PerfectSwitch::collateStats() { } + void PerfectSwitch::print(std::ostream& out) const { diff --git a/src/mem/ruby/network/simple/PerfectSwitch.hh b/src/mem/ruby/network/simple/PerfectSwitch.hh index 2f914f39b..c01c50a3b 100644 --- a/src/mem/ruby/network/simple/PerfectSwitch.hh +++ b/src/mem/ruby/network/simple/PerfectSwitch.hh @@ -67,18 +67,15 @@ class PerfectSwitch : public Consumer void init(SimpleNetwork *); void addInPort(const std::vector<MessageBuffer*>& in); void addOutPort(const std::vector<MessageBuffer*>& out, - const NetDest& routing_table_entry); - void clearRoutingTables(); - void clearBuffers(); - void reconfigureOutPort(const NetDest& routing_table_entry); + const NetDest& routing_table_entry); int getInLinks() const { return m_in.size(); } int getOutLinks() const { return m_out.size(); } void wakeup(); void storeEventInfo(int info); - void printStats(std::ostream& out) const; void clearStats(); + void collateStats(); void print(std::ostream& out) const; private: diff --git a/src/mem/ruby/network/simple/SimpleNetwork.cc b/src/mem/ruby/network/simple/SimpleNetwork.cc index b71631d26..41f587d47 100644 --- a/src/mem/ruby/network/simple/SimpleNetwork.cc +++ b/src/mem/ruby/network/simple/SimpleNetwork.cc @@ -206,76 +206,39 @@ SimpleNetwork::getThrottles(NodeID id) const } void -SimpleNetwork::printStats(ostream& out) const +SimpleNetwork::regStats() { - out << endl; - out << "Network Stats" << endl; - out << "-------------" << endl; - out << endl; - - // - // Determine total counts before printing out each switch's stats - // - std::vector<uint64> total_msg_counts; - total_msg_counts.resize(MessageSizeType_NUM); - for (MessageSizeType type = MessageSizeType_FIRST; - type < MessageSizeType_NUM; - ++type) { - total_msg_counts[type] = 0; - } - - for (int i = 0; i < m_switches.size(); i++) { - const std::vector<Throttle*>* throttles = - m_switches[i]->getThrottles(); - - for (int p = 0; p < throttles->size(); p++) { - - const std::vector<std::vector<int> >& message_counts = - ((*throttles)[p])->getCounters(); - - for (MessageSizeType type = MessageSizeType_FIRST; - type < MessageSizeType_NUM; - ++type) { - - const std::vector<int> &mct = message_counts[type]; - int sum = accumulate(mct.begin(), mct.end(), 0); - total_msg_counts[type] += uint64(sum); - } - } - } - uint64 total_msgs = 0; - uint64 total_bytes = 0; - for (MessageSizeType type = MessageSizeType_FIRST; - type < MessageSizeType_NUM; - ++type) { - - if (total_msg_counts[type] > 0) { - out << "total_msg_count_" << type << ": " << total_msg_counts[type] - << " " << total_msg_counts[type] * - uint64(MessageSizeType_to_int(type)) - << endl; - - total_msgs += total_msg_counts[type]; - - total_bytes += total_msg_counts[type] * - uint64(MessageSizeType_to_int(type)); + m_msg_counts.resize(MessageSizeType_NUM); + m_msg_bytes.resize(MessageSizeType_NUM); + + for (MessageSizeType type = MessageSizeType_FIRST; + type < MessageSizeType_NUM; ++type) { + m_msg_counts[(unsigned int) type] + .name(name() + ".msg_count." + MessageSizeType_to_string(type)) + .flags(Stats::nozero) + ; + m_msg_bytes[(unsigned int) type] + .name(name() + ".msg_byte." + MessageSizeType_to_string(type)) + .flags(Stats::nozero) + ; + + // Now state what the formula is. + for (int i = 0; i < m_switches.size(); i++) { + m_msg_counts[(unsigned int) type] += + sum(m_switches[i]->getMsgCount(type)); } - } - - out << "total_msgs: " << total_msgs - << " total_bytes: " << total_bytes << endl; - - out << endl; - for (int i = 0; i < m_switches.size(); i++) { - m_switches[i]->printStats(out); + + m_msg_bytes[(unsigned int) type] = + m_msg_counts[(unsigned int) type] * Stats::constant( + Network::MessageSizeType_to_int(type)); } } void -SimpleNetwork::clearStats() +SimpleNetwork::collateStats() { for (int i = 0; i < m_switches.size(); i++) { - m_switches[i]->clearStats(); + m_switches[i]->collateStats(); } } diff --git a/src/mem/ruby/network/simple/SimpleNetwork.hh b/src/mem/ruby/network/simple/SimpleNetwork.hh index e720d8445..06db20c0b 100644 --- a/src/mem/ruby/network/simple/SimpleNetwork.hh +++ b/src/mem/ruby/network/simple/SimpleNetwork.hh @@ -56,8 +56,8 @@ class SimpleNetwork : public Network int getEndpointBandwidth() { return m_endpoint_bandwidth; } bool getAdaptiveRouting() {return m_adaptive_routing; } - void printStats(std::ostream& out) const; - void clearStats(); + void collateStats(); + void regStats(); // returns the queue requested for the given component MessageBuffer* getToNetQueue(NodeID id, bool ordered, int network_num, std::string vnet_type); @@ -90,9 +90,7 @@ class SimpleNetwork : public Network void addLink(SwitchID src, SwitchID dest, int link_latency); void makeLink(SwitchID src, SwitchID dest, const NetDest& routing_table_entry, int link_latency); - SwitchID createSwitch(); void makeTopology(); - void linkTopology(); // Private copy constructor and assignment operator SimpleNetwork(const SimpleNetwork& obj); @@ -111,6 +109,10 @@ class SimpleNetwork : public Network int m_buffer_size; int m_endpoint_bandwidth; bool m_adaptive_routing; + + //Statistical variables + std::vector<Stats::Formula> m_msg_counts; + std::vector<Stats::Formula> m_msg_bytes; }; inline std::ostream& diff --git a/src/mem/ruby/network/simple/Switch.cc b/src/mem/ruby/network/simple/Switch.cc index b90b6eac0..c28bbdd86 100644 --- a/src/mem/ruby/network/simple/Switch.cc +++ b/src/mem/ruby/network/simple/Switch.cc @@ -44,6 +44,8 @@ using m5::stl_helpers::operator<<; Switch::Switch(const Params *p) : BasicRouter(p) { m_perfect_switch = new PerfectSwitch(m_id, this, p->virt_nets); + m_msg_counts.resize(MessageSizeType_NUM); + m_msg_bytes.resize(MessageSizeType_NUM); } Switch::~Switch() @@ -110,29 +112,6 @@ Switch::addOutPort(const vector<MessageBuffer*>& out, throttle_ptr->addLinks(intermediateBuffers, out); } -void -Switch::clearRoutingTables() -{ - m_perfect_switch->clearRoutingTables(); -} - -void -Switch::clearBuffers() -{ - m_perfect_switch->clearBuffers(); - for (int i = 0; i < m_throttles.size(); i++) { - if (m_throttles[i] != NULL) { - m_throttles[i]->clear(); - } - } -} - -void -Switch::reconfigureOutPort(const NetDest& routing_table_entry) -{ - m_perfect_switch->reconfigureOutPort(routing_table_entry); -} - const Throttle* Switch::getThrottle(LinkID link_number) const { @@ -147,77 +126,54 @@ Switch::getThrottles() const } void -Switch::printStats(std::ostream& out) const +Switch::regStats() { - ccprintf(out, "switch_%d_inlinks: %d\n", m_id, - m_perfect_switch->getInLinks()); - ccprintf(out, "switch_%d_outlinks: %d\n", m_id, - m_perfect_switch->getOutLinks()); - - // Average link utilizations - double average_utilization = 0.0; - int throttle_count = 0; - - for (int i = 0; i < m_throttles.size(); i++) { - Throttle* throttle_ptr = m_throttles[i]; - if (throttle_ptr) { - average_utilization += throttle_ptr->getUtilization(); - throttle_count++; - } - } - average_utilization = - throttle_count == 0 ? 0 : average_utilization / throttle_count; - - // Individual link utilizations - out << "links_utilized_percent_switch_" << m_id << ": " - << average_utilization << endl; - for (int link = 0; link < m_throttles.size(); link++) { - Throttle* throttle_ptr = m_throttles[link]; - if (throttle_ptr != NULL) { - out << " links_utilized_percent_switch_" << m_id - << "_link_" << link << ": " - << throttle_ptr->getUtilization() << " bw: " - << throttle_ptr->getLinkBandwidth() - << " base_latency: " << throttle_ptr->getLatency() << endl; - } + m_throttles[link]->regStats(name()); } - out << endl; - - // Traffic breakdown - for (int link = 0; link < m_throttles.size(); link++) { - Throttle* throttle_ptr = m_throttles[link]; - if (!throttle_ptr) - continue; - const vector<vector<int> >& message_counts = - throttle_ptr->getCounters(); - for (int int_type = 0; int_type < MessageSizeType_NUM; int_type++) { - MessageSizeType type = MessageSizeType(int_type); - const vector<int> &mct = message_counts[type]; - int sum = accumulate(mct.begin(), mct.end(), 0); - if (sum == 0) - continue; - - out << " outgoing_messages_switch_" << m_id - << "_link_" << link << "_" << type << ": " << sum << " " - << sum * m_network_ptr->MessageSizeType_to_int(type) - << " "; - out << mct; - out << " base_latency: " - << throttle_ptr->getLatency() << endl; + m_avg_utilization.name(name() + ".percent_links_utilized"); + for (unsigned int i = 0; i < m_throttles.size(); i++) { + m_avg_utilization += m_throttles[i]->getUtilization(); + } + m_avg_utilization /= Stats::constant(m_throttles.size()); + + for (unsigned int type = MessageSizeType_FIRST; + type < MessageSizeType_NUM; ++type) { + m_msg_counts[type] + .name(name() + ".msg_count." + + MessageSizeType_to_string(MessageSizeType(type))) + .flags(Stats::nozero) + ; + m_msg_bytes[type] + .name(name() + ".msg_bytes." + + MessageSizeType_to_string(MessageSizeType(type))) + .flags(Stats::nozero) + ; + + for (unsigned int i = 0; i < m_throttles.size(); i++) { + m_msg_counts[type] += m_throttles[i]->getMsgCount(type); } + m_msg_bytes[type] = m_msg_counts[type] * Stats::constant( + Network::MessageSizeType_to_int(MessageSizeType(type))); } - out << endl; } void -Switch::clearStats() +Switch::resetStats() { m_perfect_switch->clearStats(); for (int i = 0; i < m_throttles.size(); i++) { - if (m_throttles[i] != NULL) - m_throttles[i]->clearStats(); + m_throttles[i]->clearStats(); + } +} + +void +Switch::collateStats() +{ + m_perfect_switch->collateStats(); + for (int i = 0; i < m_throttles.size(); i++) { + m_throttles[i]->collateStats(); } } diff --git a/src/mem/ruby/network/simple/Switch.hh b/src/mem/ruby/network/simple/Switch.hh index f60a31ab3..47f4c0858 100644 --- a/src/mem/ruby/network/simple/Switch.hh +++ b/src/mem/ruby/network/simple/Switch.hh @@ -67,12 +67,13 @@ class Switch : public BasicRouter int bw_multiplier); const Throttle* getThrottle(LinkID link_number) const; const std::vector<Throttle*>* getThrottles() const; - void clearRoutingTables(); - void clearBuffers(); - void reconfigureOutPort(const NetDest& routing_table_entry); - void printStats(std::ostream& out) const; - void clearStats(); + void resetStats(); + void collateStats(); + void regStats(); + const Stats::Formula & getMsgCount(unsigned int type) const + { return m_msg_counts[type]; } + void print(std::ostream& out) const; void init_net_ptr(SimpleNetwork* net_ptr) { m_network_ptr = net_ptr; } @@ -88,6 +89,11 @@ class Switch : public BasicRouter SimpleNetwork* m_network_ptr; std::vector<Throttle*> m_throttles; std::vector<MessageBuffer*> m_buffers_to_free; + + // Statistical variables + Stats::Formula m_avg_utilization; + std::vector<Stats::Formula> m_msg_counts; + std::vector<Stats::Formula> m_msg_bytes; }; inline std::ostream& diff --git a/src/mem/ruby/network/simple/Throttle.cc b/src/mem/ruby/network/simple/Throttle.cc index 88abe4167..4a5616153 100644 --- a/src/mem/ruby/network/simple/Throttle.cc +++ b/src/mem/ruby/network/simple/Throttle.cc @@ -79,16 +79,11 @@ Throttle::init(NodeID node, Cycles link_latency, m_endpoint_bandwidth = endpoint_bandwidth; m_wakeups_wo_switch = 0; - clearStats(); -} -void -Throttle::clear() -{ - for (int counter = 0; counter < m_vnets; counter++) { - m_in[counter]->clear(); - m_out[counter]->clear(); - } + m_msg_counts.resize(MessageSizeType_NUM); + m_msg_bytes.resize(MessageSizeType_NUM); + + m_link_utilization_proxy = 0; } void @@ -99,14 +94,6 @@ Throttle::addLinks(const std::vector<MessageBuffer*>& in_vec, for (int i=0; i<in_vec.size(); i++) { addVirtualNetwork(in_vec[i], out_vec[i]); } - - m_message_counters.resize(MessageSizeType_NUM); - for (int i = 0; i < MessageSizeType_NUM; i++) { - m_message_counters[i].resize(in_vec.size()); - for (int j = 0; j<m_message_counters[i].size(); j++) { - m_message_counters[i][j] = 0; - } - } } void @@ -179,7 +166,7 @@ Throttle::wakeup() m_in[vnet]->pop(); // Count the message - m_message_counters[net_msg_ptr->getMessageSize()][vnet]++; + m_msg_counts[net_msg_ptr->getMessageSize()][vnet]++; DPRINTF(RubyNetwork, "%s\n", *m_out[vnet]); } @@ -208,7 +195,7 @@ Throttle::wakeup() double ratio = 1.0 - (double(bw_remaining) / double(getLinkBandwidth())); // If ratio = 0, we used no bandwidth, if ratio = 1, we used all - linkUtilized(ratio); + m_link_utilization_proxy += ratio; if (bw_remaining > 0 && !schedule_wakeup) { // We have extra bandwidth and our output buffer was @@ -225,29 +212,41 @@ Throttle::wakeup() } void -Throttle::printStats(ostream& out) const +Throttle::regStats(string parent) { - out << "utilized_percent: " << getUtilization() << endl; + m_link_utilization + .name(parent + csprintf(".throttle%i", m_node) + ".link_utilization"); + + for (MessageSizeType type = MessageSizeType_FIRST; + type < MessageSizeType_NUM; ++type) { + m_msg_counts[(unsigned int)type] + .init(m_vnets) + .name(parent + csprintf(".throttle%i", m_node) + ".msg_count." + + MessageSizeType_to_string(type)) + .flags(Stats::nozero) + ; + m_msg_bytes[(unsigned int) type] + .name(parent + csprintf(".throttle%i", m_node) + ".msg_bytes." + + MessageSizeType_to_string(type)) + .flags(Stats::nozero) + ; + + m_msg_bytes[(unsigned int) type] = m_msg_counts[type] * Stats::constant( + Network::MessageSizeType_to_int(type)); + } } void Throttle::clearStats() { - m_ruby_start = g_system_ptr->curCycle(); - m_links_utilized = 0.0; - - for (int i = 0; i < m_message_counters.size(); i++) { - for (int j = 0; j < m_message_counters[i].size(); j++) { - m_message_counters[i][j] = 0; - } - } + m_link_utilization_proxy = 0; } -double -Throttle::getUtilization() const +void +Throttle::collateStats() { - return 100.0 * double(m_links_utilized) / - double(g_system_ptr->curCycle()-m_ruby_start); + m_link_utilization = 100.0 * m_link_utilization_proxy + / (double(g_system_ptr->curCycle() - g_ruby_start)); } void diff --git a/src/mem/ruby/network/simple/Throttle.hh b/src/mem/ruby/network/simple/Throttle.hh index 2ca474f41..b21af4d64 100644 --- a/src/mem/ruby/network/simple/Throttle.hh +++ b/src/mem/ruby/network/simple/Throttle.hh @@ -63,32 +63,29 @@ class Throttle : public Consumer { return csprintf("Throttle-%i", m_sID); } void addLinks(const std::vector<MessageBuffer*>& in_vec, - const std::vector<MessageBuffer*>& out_vec); + const std::vector<MessageBuffer*>& out_vec); void wakeup(); - void printStats(std::ostream& out) const; - void clearStats(); - // The average utilization (a percent) since last clearStats() - double getUtilization() const; + // The average utilization (a fraction) since last clearStats() + const Stats::Scalar & getUtilization() const + { return m_link_utilization; } + const Stats::Vector & getMsgCount(unsigned int type) const + { return m_msg_counts[type]; } + int getLinkBandwidth() const { return m_endpoint_bandwidth * m_link_bandwidth_multiplier; } Cycles getLatency() const { return m_link_latency; } - const std::vector<std::vector<int> >& - getCounters() const - { - return m_message_counters; - } - - void clear(); + void clearStats(); + void collateStats(); + void regStats(std::string name); void print(std::ostream& out) const; private: void init(NodeID node, Cycles link_latency, int link_bandwidth_multiplier, int endpoint_bandwidth); void addVirtualNetwork(MessageBuffer* in_ptr, MessageBuffer* out_ptr); - void linkUtilized(double ratio) { m_links_utilized += ratio; } // Private copy constructor and assignment operator Throttle(const Throttle& obj); @@ -96,8 +93,7 @@ class Throttle : public Consumer std::vector<MessageBuffer*> m_in; std::vector<MessageBuffer*> m_out; - std::vector<std::vector<int> > m_message_counters; - int m_vnets; + unsigned int m_vnets; std::vector<int> m_units_remaining; int m_sID; NodeID m_node; @@ -106,9 +102,12 @@ class Throttle : public Consumer int m_wakeups_wo_switch; int m_endpoint_bandwidth; - // For tracking utilization - Cycles m_ruby_start; - double m_links_utilized; + // Statistical variables + Stats::Scalar m_link_utilization; + std::vector<Stats::Vector> m_msg_counts; + std::vector<Stats::Formula> m_msg_bytes; + + double m_link_utilization_proxy; }; inline std::ostream& diff --git a/src/mem/ruby/system/System.cc b/src/mem/ruby/system/System.cc index 4fb6bbde1..1f209f785 100644 --- a/src/mem/ruby/system/System.cc +++ b/src/mem/ruby/system/System.cc @@ -140,11 +140,9 @@ RubySystem::printStats(ostream& out) tm *localTime = localtime(&T); char buf[100]; strftime(buf, 100, "%b/%d/%Y %H:%M:%S", localTime); - out << "Real time: " << buf << endl; m_profiler_ptr->printStats(out); - m_network_ptr->printStats(out); } void @@ -410,7 +408,6 @@ void RubySystem::resetStats() { m_profiler_ptr->clearStats(); - m_network_ptr->clearStats(); for (uint32_t cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) { m_abs_cntrl_vec[cntrl]->clearStats(); } diff --git a/src/mem/ruby/system/System.hh b/src/mem/ruby/system/System.hh index ea55a23e0..474741bf7 100644 --- a/src/mem/ruby/system/System.hh +++ b/src/mem/ruby/system/System.hh @@ -104,9 +104,6 @@ class RubySystem : public ClockedObject void printStats(std::ostream& out); void resetStats(); - - uint64 getInstructionCount(int thread) { return 1; } - void print(std::ostream& out) const; void serialize(std::ostream &os); |