summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/stat-tool.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpgpu-sim/stat-tool.h')
-rw-r--r--src/gpgpu-sim/stat-tool.h251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/gpgpu-sim/stat-tool.h b/src/gpgpu-sim/stat-tool.h
index 3ebe750..ebac6c2 100644
--- a/src/gpgpu-sim/stat-tool.h
+++ b/src/gpgpu-sim/stat-tool.h
@@ -67,9 +67,260 @@
#define STAT_TOOL_H
#include "../abstract_hardware_model.h"
+#include "histogram.h"
+
#include <stdio.h>
#include <zlib.h>
+// detect gcc 4.3 and use unordered map (part of c++0x)
+// unordered map doesn't play nice with _GLIBCXX_DEBUG, just use a map if its enabled.
+#if defined( __GNUC__ ) and not defined( _GLIBCXX_DEBUG )
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 3
+ #include <unordered_map>
+ #define my_hash_map std::unordered_map
+#else
+ #include <ext/hash_map>
+ namespace std {
+ using namespace __gnu_cxx;
+ }
+ #define my_hash_map std::hash_map
+#endif
+#else
+ #include <map>
+ #define my_hash_map std::map
+ #define USE_MAP
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////
+// logger snapshot trigger:
+// - automate the snap_shot part of loggers to avoid modifying simulation loop everytime
+// a new time-dependent stat is added
+/////////////////////////////////////////////////////////////////////////////////////
+
+class snap_shot_trigger {
+public:
+ snap_shot_trigger(unsigned long long interval) : m_snap_shot_interval(interval) {}
+ virtual ~snap_shot_trigger() {}
+
+ void try_snap_shot(unsigned long long current_cycle) {
+ if ((current_cycle % m_snap_shot_interval == 0) && current_cycle != 0) {
+ snap_shot(current_cycle);
+ }
+ }
+
+ virtual void snap_shot(unsigned long long current_cycle) = 0;
+
+ const unsigned long long & get_interval() const { return m_snap_shot_interval;}
+
+protected:
+ unsigned long long m_snap_shot_interval;
+};
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+// spill log interface:
+// - unified interface to spill log to file to avoid infinite memory usage for logging
+/////////////////////////////////////////////////////////////////////////////////////
+
+class spill_log_interface {
+public:
+ spill_log_interface() {}
+ virtual ~spill_log_interface() {}
+
+ virtual void spill(FILE *fout, bool final) = 0;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////
+// thread control-flow locality logger
+/////////////////////////////////////////////////////////////////////////////////////
+
+class thread_insn_span {
+public:
+ thread_insn_span(unsigned long long cycle, int n_insn);
+ thread_insn_span(const thread_insn_span& other);
+ ~thread_insn_span();
+
+ thread_insn_span& operator=(const thread_insn_span& other);
+ thread_insn_span& operator+=(const thread_insn_span& other);
+ void set_span( address_type pc );
+ void reset(unsigned long long cycle);
+
+ void print_span(FILE *fout) const;
+ void print_histo(FILE *fout) const;
+ void print_sparse_histo(FILE *fout) const;
+ void print_sparse_histo(gzFile fout) const;
+
+private:
+ typedef my_hash_map<address_type, int> span_count_map;
+ unsigned long long m_cycle;
+ int m_n_insn;
+ span_count_map m_insn_span_count;
+};
+
+class thread_CFlocality : public snap_shot_trigger, public spill_log_interface {
+public:
+ thread_CFlocality(std::string name, unsigned long long snap_shot_interval,
+ int nthreads, int n_insn, address_type start_pc, unsigned long long start_cycle = 0);
+ ~thread_CFlocality();
+
+ void update_thread_pc( int thread_id, address_type pc );
+ void snap_shot(unsigned long long current_cycle);
+ void spill(FILE *fout, bool final);
+
+ void print_visualizer(FILE *fout);
+ void print_visualizer(gzFile fout);
+ void print_span(FILE *fout) const;
+ void print_histo(FILE *fout) const;
+private:
+ std::string m_name;
+
+ int m_nthreads;
+ std::vector<address_type> m_thread_pc;
+
+ unsigned long long m_cycle;
+ thread_insn_span m_thd_span;
+ std::list<thread_insn_span> m_thd_span_archive;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////
+// per-insn active thread distribution (warp occ) logger
+/////////////////////////////////////////////////////////////////////////////////////
+
+class insn_warp_occ_logger {
+public:
+ insn_warp_occ_logger(int simd_width, int n_insn)
+ : m_simd_width(simd_width),
+ m_insn_warp_occ(n_insn, linear_histogram(1, "", m_simd_width)),
+ m_id(s_ids++) {}
+
+ insn_warp_occ_logger(const insn_warp_occ_logger& other)
+ : m_simd_width(other.m_simd_width),
+ m_insn_warp_occ(other.m_insn_warp_occ.size(), linear_histogram(1, "", m_simd_width)),
+ m_id(s_ids++) {}
+
+ ~insn_warp_occ_logger() {}
+
+ insn_warp_occ_logger& operator=(const insn_warp_occ_logger& p) {
+ printf("insn_warp_occ_logger Operator= called: %02d \n", m_id);
+ assert(0);
+ return *this;
+ }
+
+ void set_id(int id) { m_id = id; }
+
+ void log(address_type pc, int warp_occ) {
+ m_insn_warp_occ[pc].add2bin(warp_occ - 1);
+ }
+
+ void print(FILE *fout) const
+ {
+ for (unsigned i = 0; i < m_insn_warp_occ.size(); i++) {
+ fprintf(fout, "InsnWarpOcc%02d-%d", m_id, i);
+ m_insn_warp_occ[i].fprint(fout);
+ fprintf(fout, "\n");
+ }
+ }
+
+private:
+
+ int m_simd_width;
+ std::vector<linear_histogram> m_insn_warp_occ;
+ int m_id;
+ static int s_ids;
+};
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+// generic linear histogram logger
+/////////////////////////////////////////////////////////////////////////////////////
+
+class linear_histogram_snapshot {
+public:
+ linear_histogram_snapshot(int n_bins, unsigned long long cycle)
+ : m_cycle(cycle),
+ m_linear_histogram(n_bins,0)
+ { }
+
+ linear_histogram_snapshot(const linear_histogram_snapshot& other)
+ : m_cycle(other.m_cycle),
+ m_linear_histogram(other.m_linear_histogram)
+ { }
+
+ ~linear_histogram_snapshot() { }
+
+ void addsample(int pos) {
+ assert((size_t)pos < m_linear_histogram.size());
+ m_linear_histogram[pos] += 1;
+ }
+
+ void subsample(int pos) {
+ assert((size_t)pos < m_linear_histogram.size());
+ m_linear_histogram[pos] -= 1;
+ }
+
+ void reset(unsigned long long cycle) {
+ m_cycle = cycle;
+ m_linear_histogram.assign(m_linear_histogram.size(), 0);
+ }
+
+ void set_cycle(unsigned long long cycle) { m_cycle = cycle; }
+
+ void print(FILE *fout) const {
+ fprintf(fout, "%d = ", (int)m_cycle);
+ for (unsigned int i = 0; i < m_linear_histogram.size(); i++) {
+ fprintf(fout, "%d ", m_linear_histogram[i]);
+ }
+ }
+
+ void print_visualizer(FILE *fout) const {
+ for (unsigned int i = 0; i < m_linear_histogram.size(); i++) {
+ fprintf(fout, "%d ", m_linear_histogram[i]);
+ }
+ }
+
+ void print_visualizer(gzFile fout) const {
+ for (unsigned int i = 0; i < m_linear_histogram.size(); i++) {
+ gzprintf(fout, "%d ", m_linear_histogram[i]);
+ }
+ }
+
+private:
+ unsigned long long m_cycle;
+ std::vector<int> m_linear_histogram;
+};
+
+class linear_histogram_logger : public snap_shot_trigger, public spill_log_interface {
+public:
+ linear_histogram_logger(int n_bins,
+ unsigned long long snap_shot_interval,
+ const char *name,
+ bool reset_at_snap_shot = true,
+ unsigned long long start_cycle = 0);
+ linear_histogram_logger(const linear_histogram_logger& other);
+
+ ~linear_histogram_logger();
+
+ void set_id(int id) { m_id = id; }
+ void log(int pos) { m_curr_lin_hist.addsample(pos); }
+ void unlog(int pos) { m_curr_lin_hist.subsample(pos); }
+ void snap_shot(unsigned long long current_cycle);
+ void spill(FILE *fout, bool final);
+
+ void print(FILE *fout) const;
+ void print_visualizer(FILE *fout);
+ void print_visualizer(gzFile fout);
+
+private:
+ int m_n_bins;
+ linear_histogram_snapshot m_curr_lin_hist;
+ std::list<linear_histogram_snapshot> m_lin_hist_archive;
+ unsigned long long m_cycle;
+ bool m_reset_at_snap_shot;
+ std::string m_name;
+ int m_id;
+ static int s_ids;
+};
+
void try_snap_shot (unsigned long long current_cycle);
void set_spill_interval (unsigned long long interval);
void spill_log_to_file (FILE *fout, int final, unsigned long long current_cycle);