diff options
Diffstat (limited to 'src/gpgpu-sim')
| -rw-r--r-- | src/gpgpu-sim/Makefile | 20 | ||||
| -rw-r--r-- | src/gpgpu-sim/dram.cc | 32 | ||||
| -rw-r--r-- | src/gpgpu-sim/dram.h | 11 | ||||
| -rw-r--r-- | src/gpgpu-sim/dram_sched.cc | 11 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-cache.cc | 29 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-cache.h | 49 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.cc | 183 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.h | 123 | ||||
| -rw-r--r-- | src/gpgpu-sim/icnt_wrapper.cc | 2 | ||||
| -rw-r--r-- | src/gpgpu-sim/icnt_wrapper.h | 3 | ||||
| -rw-r--r-- | src/gpgpu-sim/l2cache.cc | 96 | ||||
| -rw-r--r-- | src/gpgpu-sim/l2cache.h | 21 | ||||
| -rw-r--r-- | src/gpgpu-sim/mem_fetch.cc | 15 | ||||
| -rw-r--r-- | src/gpgpu-sim/mem_fetch.h | 6 | ||||
| -rw-r--r-- | src/gpgpu-sim/mem_fetch_status.tup | 2 | ||||
| -rw-r--r-- | src/gpgpu-sim/mem_latency_stat.cc | 8 | ||||
| -rw-r--r-- | src/gpgpu-sim/mem_latency_stat.h | 9 | ||||
| -rw-r--r-- | src/gpgpu-sim/power_interface.cc | 125 | ||||
| -rw-r--r-- | src/gpgpu-sim/power_interface.h | 43 | ||||
| -rw-r--r-- | src/gpgpu-sim/power_stat.cc | 335 | ||||
| -rw-r--r-- | src/gpgpu-sim/power_stat.h | 613 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 452 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.h | 308 | ||||
| -rw-r--r-- | src/gpgpu-sim/stats.h | 7 | ||||
| -rw-r--r-- | src/gpgpu-sim/visualizer.cc | 5 |
25 files changed, 2416 insertions, 92 deletions
diff --git a/src/gpgpu-sim/Makefile b/src/gpgpu-sim/Makefile index fdb4503..04659aa 100644 --- a/src/gpgpu-sim/Makefile +++ b/src/gpgpu-sim/Makefile @@ -52,6 +52,11 @@ else CXXFLAGS += endif +POWER_FLAGS= +ifneq ($(GPGPUSIM_POWER_MODEL),) + POWER_FLAGS = -I$(GPGPUSIM_POWER_MODEL) -DGPGPUSIM_POWER_MODEL +endif + OPTFLAGS += -g3 -fPIC CPP = g++ $(SNOW) @@ -60,7 +65,16 @@ OEXT = o OUTPUT_DIR=../../$(SIM_OBJ_FILES_DIR)/gpgpu-sim SRCS = $(shell ls *.cc) -OBJS = $(SRCS:%.cc=$(OUTPUT_DIR)/%.$(OEXT)) + +EXCLUDES = + +ifeq ($(GPGPUSIM_POWER_MODEL), ) +EXCLUDES += power_interface.cc +endif + +CSRCS = $(filter-out $(EXCLUDES), $(SRCS)) + +OBJS = $(CSRCS:%.cc=$(OUTPUT_DIR)/%.$(OEXT)) libgpu_uarch_sim.a:$(OBJS) ar rcs $(OUTPUT_DIR)/libgpu_uarch_sim.a $(OBJS) @@ -69,13 +83,13 @@ Makefile.makedepend: depend depend: touch Makefile.makedepend - makedepend -fMakefile.makedepend -p$(OUTPUT_DIR)/ $(SRCS) 2> /dev/null + makedepend -fMakefile.makedepend -p$(OUTPUT_DIR)/ $(CSRCS) 2> /dev/null $(OUTPUT_DIR)/l2cache.$(OEXT): l2cache.cc $(CPP) $(OPTFLAGS) $(CXXFLAGS_L2CACHE) -o $*.$(OEXT) -c l2cache.cc $(OUTPUT_DIR)/%.$(OEXT): %.cc - $(CPP) $(OPTFLAGS) $(CXXFLAGS) -o $(OUTPUT_DIR)/$*.$(OEXT) -c $*.cc + $(CPP) $(OPTFLAGS) $(CXXFLAGS) $(POWER_FLAGS) -o $(OUTPUT_DIR)/$*.$(OEXT) -c $*.cc clean: rm -f *.o core *~ *.a diff --git a/src/gpgpu-sim/dram.cc b/src/gpgpu-sim/dram.cc index a173a52..3594198 100644 --- a/src/gpgpu-sim/dram.cc +++ b/src/gpgpu-sim/dram.cc @@ -419,6 +419,17 @@ void dram_t::cycle() #endif } +void dram_t::get_access_stats(unsigned &total_access, unsigned &total_reads, unsigned &total_writes,unsigned &total_l2_read_access,unsigned &total_l2_read_miss,unsigned &total_l2_write_access,unsigned &total_l2_write_miss ){ + total_access += m_stats->total_n_access; + total_reads += m_stats->total_n_reads; + total_writes += m_stats->total_n_writes; + total_l2_read_access += m_stats->L2_read_access; + total_l2_read_miss += m_stats->L2_read_miss; + total_l2_write_access += m_stats->L2_write_access; + total_l2_write_miss += m_stats->L2_write_miss; + +} + //if mrq is being serviced by dram, gets popped after CL latency fulfilled class mem_fetch* dram_t::pop() { @@ -525,3 +536,24 @@ void dram_t::visualizer_print( gzFile visualizer_file ) m_stats->mem_access_type_stats[TEXTURE_ACC_R][id][j]); } } + + +void dram_t::set_dram_power_stats( unsigned &cmd, + unsigned &activity, + unsigned &nop, + unsigned &act, + unsigned &pre, + unsigned &rd, + unsigned &wr, + unsigned &req) const{ + + // Point power performance counters to low-level DRAM counters + cmd = n_cmd; + activity = n_activity; + nop = n_nop; + act = n_act; + pre = n_pre; + rd = n_rd; + wr = n_wr; + req = n_req; +} diff --git a/src/gpgpu-sim/dram.h b/src/gpgpu-sim/dram.h index ad773b3..0e82763 100644 --- a/src/gpgpu-sim/dram.h +++ b/src/gpgpu-sim/dram.h @@ -103,6 +103,7 @@ public: bool returnq_full() const; unsigned int queue_limit() const; void visualizer_print( gzFile visualizer_file ); + void get_access_stats(unsigned &total_access, unsigned &total_reads, unsigned &total_writes,unsigned &total_l2_read_hit,unsigned &total_l2_read_miss,unsigned &total_l2_write_hit,unsigned &total_l2_write_miss ); class mem_fetch* pop(); void push( class mem_fetch *data ); @@ -112,6 +113,16 @@ public: class memory_partition_unit *m_memory_partition_unit; unsigned int id; + // Power Model + void set_dram_power_stats( unsigned &cmd, + unsigned &activity, + unsigned &nop, + unsigned &act, + unsigned &pre, + unsigned &rd, + unsigned &wr, + unsigned &req) const; + private: void scheduler_fifo(); void scheduler_frfcfs(); diff --git a/src/gpgpu-sim/dram_sched.cc b/src/gpgpu-sim/dram_sched.cc index e556edc..e30bd24 100644 --- a/src/gpgpu-sim/dram_sched.cc +++ b/src/gpgpu-sim/dram_sched.cc @@ -133,6 +133,17 @@ void dram_t::scheduler_frfcfs() frfcfs_scheduler *sched = m_frfcfs_scheduler; while ( !mrqq->empty() && (!m_config->gpgpu_dram_sched_queue_size || sched->num_pending() < m_config->gpgpu_dram_sched_queue_size)) { dram_req_t *req = mrqq->pop(); + + // Power stats + //if(req->data->get_type() != READ_REPLY && req->data->get_type() != WRITE_ACK) + m_stats->total_n_access++; + + if(req->data->get_type() == WRITE_REQUEST){ + m_stats->total_n_writes++; + }else if(req->data->get_type() == READ_REQUEST){ + m_stats->total_n_reads++; + } + req->data->set_status(IN_PARTITION_MC_INPUT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); sched->add_req(req); } diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index fc2d032..3f44eea 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -201,6 +201,13 @@ void tag_array::print( FILE *stream, unsigned &total_access, unsigned &total_mis total_access+=m_access; } +void tag_array::get_stats(unsigned &total_access, unsigned &total_misses) const{ + // Get the access and miss counts from the tag array + total_misses = m_miss; + total_access = m_access; +} + + bool was_write_sent( const std::list<cache_event> &events ) { for( std::list<cache_event>::const_iterator e=events.begin(); e!=events.end(); e++ ) { @@ -293,6 +300,7 @@ void baseline_cache::cycle(){ if ( !m_memport->full(mf->get_data_size(),mf->get_is_write()) ) { m_miss_queue.pop_front(); m_memport->push(mf); + n_simt_to_mem+=mf->get_num_flits(true); // Interconnect power stats } } } @@ -393,6 +401,7 @@ cache_request_status data_cache::wr_hit_wb(new_addr_type addr, unsigned cache_in cache_block_t &block = m_tag_array.get_block(cache_index); block.m_status = MODIFIED; + m_write_access++; return HIT; } @@ -409,6 +418,7 @@ cache_request_status data_cache::wr_hit_wt(new_addr_type addr, unsigned cache_in // generate a write-through send_write_request(mf, WRITE_REQUEST_SENT, time, events); + m_write_access++; return HIT; } @@ -423,6 +433,8 @@ cache_request_status data_cache::wr_hit_we(new_addr_type addr, unsigned cache_in // Invalidate block block.m_status = INVALID; + + m_write_access++; return HIT; } @@ -481,8 +493,11 @@ enum cache_request_status data_cache::wr_miss_wa(new_addr_type addr, unsigned ca m_miss_queue.push_back(wb); wb->set_status(m_miss_queue_status,time); } - if( do_miss ) + if( do_miss ){ + m_write_access++; + m_write_miss++; return MISS; + } return RESERVATION_FAIL; } @@ -494,6 +509,9 @@ enum cache_request_status data_cache::wr_miss_no_wa(new_addr_type addr, unsigned // on miss, generate write through (no write buffering -- too many threads for that) send_write_request(mf, WRITE_REQUEST_SENT, time, events); + + m_write_access++; + m_write_miss++; return MISS; } @@ -508,6 +526,8 @@ enum cache_request_status data_cache::rd_hit_base(new_addr_type addr, unsigned c cache_block_t &block = m_tag_array.get_block(cache_index); block.m_status = MODIFIED; // mark line as dirty } + + m_read_access++; return HIT; } @@ -528,8 +548,11 @@ enum cache_request_status data_cache::rd_miss_base(new_addr_type addr, unsigned mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, L1_WRBK_ACC,m_config.get_line_sz(),true); send_write_request(wb, WRITE_BACK_REQUEST_SENT, time, events); } - if( do_miss ) + if( do_miss ){ + m_read_access++; + m_read_miss++; return MISS; + } return RESERVATION_FAIL; } @@ -565,7 +588,6 @@ enum cache_request_status l1_cache::access( new_addr_type addr, mem_fetch *mf, u unsigned cache_index = (unsigned)-1; enum cache_request_status status = m_tag_array.probe(block_addr,cache_index); - // Each function pointer ( m_[rd/wr]_[hit/miss] ) is set in the data_cache constructor to reflect the corresponding cache configuration options. // Function pointers were used to avoid many long conditional branches resulting from many cache configuration options. if(wr){ // Write @@ -652,6 +674,7 @@ void tex_cache::cycle(){ if ( !m_memport->full(mf->get_ctrl_size(),false) ) { m_request_fifo.pop(); m_memport->push(mf); + n_simt_to_mem+=mf->get_num_flits(true); // Interconnect power stats } } // read ready lines from cache diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 4516e34..783280c 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -255,14 +255,15 @@ private: friend class l2_cache; }; + class tag_array { public: - tag_array( const cache_config &config, int core_id, int type_id ); + tag_array( const cache_config &config, int core_id, int type_id ); ~tag_array(); enum cache_request_status probe( new_addr_type addr, unsigned &idx ) const; enum cache_request_status access( new_addr_type addr, unsigned time, unsigned &idx ); - enum cache_request_status access( new_addr_type addr, unsigned time, unsigned &idx, bool &wb, cache_block_t &evicted ); + enum cache_request_status access( new_addr_type addr, unsigned time, unsigned &idx, bool &wb, cache_block_t &evicted ); void fill( new_addr_type addr, unsigned time ); void fill( unsigned idx, unsigned time ); @@ -270,11 +271,12 @@ public: unsigned size() const { return m_config.get_num_lines();} cache_block_t &get_block(unsigned idx) { return m_lines[idx];} - void flush(); // flash invalidate all entries + void flush(); // flash invalidate all entries void new_window(); void print( FILE *stream, unsigned &total_access, unsigned &total_misses ) const; float windowed_miss_rate( ) const; + void get_stats(unsigned &total_access, unsigned &total_misses) const; protected: @@ -289,12 +291,13 @@ protected: // performance counters for calculating the amount of misses within a time window unsigned m_prev_snapshot_access; unsigned m_prev_snapshot_miss; - unsigned m_prev_snapshot_pending_hit; + unsigned m_prev_snapshot_pending_hit; int m_core_id; // which shader core is using this int m_type_id; // what kind of cache is this (normal, texture, constant) }; + class mshr_table { public: mshr_table( unsigned num_entries, unsigned max_merged ) @@ -366,6 +369,10 @@ public: assert(config.m_mshr_type == ASSOC); m_memport=memport; m_miss_queue_status = status; + m_read_access=0; + m_write_access=0; + m_read_miss=0; + m_write_miss=0; } virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list<cache_event> &events ) = 0; @@ -384,6 +391,21 @@ public: void print(FILE *fp, unsigned &accesses, unsigned &misses) const; void display_state( FILE *fp ) const; + virtual void get_data_stats(unsigned &read_access, unsigned &read_misses,unsigned &write_access, unsigned &write_misses) const { + read_access = m_read_access; + write_access = m_write_access; + read_misses = m_read_miss; + write_misses = m_write_miss; + } + + void get_stats(unsigned &accesses, unsigned &misses) const { + m_tag_array.get_stats(accesses, misses); + } + + void set_icnt_power_stats(unsigned &simt_to_mem) const{ + simt_to_mem = n_simt_to_mem; + } + protected: std::string m_name; const cache_config &m_config; @@ -422,6 +444,14 @@ public: /// Read miss handler. Check MSHR hit or MSHR available void send_read_request(new_addr_type addr, new_addr_type block_addr, unsigned cache_index, mem_fetch *mf, unsigned time, bool &do_miss, bool &wb, cache_block_t &evicted, std::list<cache_event> &events, bool read_only, bool wa); + + // Power stats + unsigned m_read_access; + unsigned m_write_access; + unsigned m_read_miss; + unsigned m_write_miss; + + unsigned n_simt_to_mem; // Interconnect power stats }; /// Read only cache @@ -574,6 +604,14 @@ public: mem_fetch *next_access(){return m_result_fifo.pop();} void display_state( FILE *fp ) const; + void get_stats(unsigned &accesses, unsigned &misses) const{ + m_tags.get_stats(accesses, misses); + } + + void set_icnt_power_stats(unsigned &simt_to_mem) const{ + simt_to_mem = n_simt_to_mem; + } + private: std::string m_name; const cache_config &m_config; @@ -700,6 +738,9 @@ public: typedef std::map<mem_fetch*,extra_mf_fields> extra_mf_fields_lookup; extra_mf_fields_lookup m_extra_mf_fields; + + // Interconnect power stats + unsigned n_simt_to_mem; }; #endif diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 6aeaa63..fd87299 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -26,6 +26,7 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + #include "gpu-sim.h" #include <stdio.h> @@ -33,7 +34,7 @@ #include <math.h> #include "zlib.h" -#include "../option_parser.h" + #include "shader.h" #include "dram.h" #include "mem_fetch.h" @@ -56,21 +57,27 @@ #include "../debug.h" #include "../gpgpusim_entrypoint.h" #include "../cuda-sim/cuda-sim.h" - #include "mem_latency_stat.h" +#include "power_stat.h" #include "visualizer.h" #include "stats.h" +#ifdef GPGPUSIM_POWER_MODEL +#include "power_interface.h" +#endif + #include <stdio.h> #include <string.h> #define MAX(a,b) (((a)>(b))?(a):(b)) + bool g_interactive_debugger_enabled=false; unsigned long long gpu_sim_cycle = 0; unsigned long long gpu_tot_sim_cycle = 0; + // performance counter for stalls due to congestion. unsigned int gpu_stall_dramfull = 0; unsigned int gpu_stall_icnt2sh = 0; @@ -84,8 +91,47 @@ unsigned int gpu_stall_icnt2sh = 0; #define MEM_LATENCY_STAT_IMPL + + + + #include "mem_latency_stat.h" +void power_config::reg_options(class OptionParser * opp) +{ + + + option_parser_register(opp, "-mcpat_xml_file", OPT_CSTR, + &g_power_config_name,"McPAT XML file", + "mcpat.xml"); + + option_parser_register(opp, "-power_simulation_enabled", OPT_BOOL, + &g_power_simulation_enabled, "Turn on power simulator (1=On, 0=Off)", + "1"); + + option_parser_register(opp, "-power_per_cycle_dump", OPT_BOOL, + &g_power_per_cycle_dump, "Dump detailed power output each cycle", + "0"); + + // Output Data Formats + option_parser_register(opp, "-power_trace_enabled", OPT_BOOL, + &g_power_trace_enabled, "produce a file for the power trace (1=On, 0=Off)", + "0"); + + option_parser_register(opp, "-power_trace_zlevel", OPT_INT32, + &g_power_trace_zlevel, "Compression level of the power trace output log (0=no comp, 9=highest)", + "6"); + + option_parser_register(opp, "-steady_power_levels_enabled", OPT_BOOL, + &g_steady_power_levels_enabled, "produce a file for the steady power levels (1=On, 0=Off)", + "0"); + + option_parser_register(opp, "-steady_state_definition", OPT_CSTR, + &gpu_steady_state_definition, "allowed deviation:number of samples", + "8:4"); + +} + void memory_config::reg_options(class OptionParser * opp) { option_parser_register(opp, "-gpgpu_dram_scheduler", OPT_INT32, &scheduler_type, @@ -164,6 +210,15 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_perfect_mem", OPT_BOOL, &gpgpu_perfect_mem, "enable perfect memory mode (no cache miss)", "0"); + option_parser_register(opp, "-n_regfile_gating_group", OPT_UINT32, &n_regfile_gating_group, + "group of lanes that should be read/written together)", + "4"); + option_parser_register(opp, "-gpgpu_clock_gated_reg_file", OPT_BOOL, &gpgpu_clock_gated_reg_file, + "enable clock gated reg file for power calculations", + "0"); + option_parser_register(opp, "-gpgpu_clock_gated_lanes", OPT_BOOL, &gpgpu_clock_gated_lanes, + "enable clock gated lanes for power calculations", + "0"); option_parser_register(opp, "-gpgpu_shader_registers", OPT_UINT32, &gpgpu_shader_registers, "Number of registers per shader core. Limits number of concurrent CTAs. (default 8192)", "8192"); @@ -277,7 +332,7 @@ void gpgpu_sim_config::reg_options(option_parser_t opp) gpgpu_functional_sim_config::reg_options(opp); m_shader_config.reg_options(opp); m_memory_config.reg_options(opp); - + power_config::reg_options(opp); option_parser_register(opp, "-gpgpu_max_cycle", OPT_INT32, &gpu_max_cycle_opt, "terminates gpu simulation early (0 = no limit)", "0"); @@ -290,9 +345,13 @@ void gpgpu_sim_config::reg_options(option_parser_t opp) option_parser_register(opp, "-gpgpu_runtime_stat", OPT_CSTR, &gpgpu_runtime_stat, "display runtime statistics such as dram utilization {<freq>:<flag>}", "10000:0"); - option_parser_register(opp, "-gpgpu_flush_cache", OPT_BOOL, &gpgpu_flush_cache, - "Flush cache at the end of each kernel call", + option_parser_register(opp, "-gpgpu_flush_l1_cache", OPT_BOOL, &gpgpu_flush_l1_cache, + "Flush L1 cache at the end of each kernel call", "0"); + option_parser_register(opp, "-gpgpu_flush_l2_cache", OPT_BOOL, &gpgpu_flush_l2_cache, + "Flush L2 cache at the end of each kernel call", + "0"); + option_parser_register(opp, "-gpgpu_deadlock_detect", OPT_BOOL, &gpu_deadlock_detect, "Stop the simulation at deadlock (1=on (default), 0=off)", "1"); @@ -427,14 +486,22 @@ gpgpu_sim::gpgpu_sim( const gpgpu_sim_config &config ) set_ptx_warp_size(m_shader_config); ptx_file_line_stats_create_exposed_latency_tracker(m_config.num_shader()); +#ifdef GPGPUSIM_POWER_MODEL + m_gpgpusim_wrapper = new gpgpu_sim_wrapper(); +#endif + m_shader_stats = new shader_core_stats(m_shader_config); m_memory_stats = new memory_stats_t(m_config.num_shader(),m_shader_config,m_memory_config); + average_pipeline_duty_cycle = (float *)malloc(sizeof(float)); + active_sms=(float *)malloc(sizeof(float)); + m_power_stats = new power_stat_t(m_shader_config,average_pipeline_duty_cycle,active_sms,m_shader_stats,m_memory_config,m_memory_stats); gpu_sim_insn = 0; gpu_tot_sim_insn = 0; gpu_tot_issued_cta = 0; gpu_deadlock = false; + m_cluster = new simt_core_cluster*[m_shader_config->n_simt_clusters]; for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) m_cluster[i] = new simt_core_cluster(this,i,m_shader_config,m_memory_config,m_shader_stats,m_memory_stats); @@ -451,6 +518,8 @@ gpgpu_sim::gpgpu_sim( const gpgpu_sim_config &config ) m_running_kernels.resize( config.max_concurrent_kernel, NULL ); m_last_issued_kernel = 0; m_last_cluster_issue = 0; + *average_pipeline_duty_cycle=0; + *active_sms=0; } int gpgpu_sim::shared_mem_size() const @@ -564,6 +633,13 @@ void gpgpu_sim::init() if (g_network_mode) icnt_init_grid(); + + // McPAT initialization function. Called on first launch of GPU +#ifdef GPGPUSIM_POWER_MODEL + if(m_config.g_power_simulation_enabled){ + init_mcpat(m_config, m_gpgpusim_wrapper, m_config.gpu_stat_sample_freq, gpu_tot_sim_insn, gpu_sim_insn); + } +#endif } void gpgpu_sim::update_stats() { @@ -626,7 +702,7 @@ void gpgpu_sim::deadlock_check() } } -void gpgpu_sim::gpu_print_stat() const +void gpgpu_sim::gpu_print_stat() { printf("gpu_sim_cycle = %lld\n", gpu_sim_cycle); printf("gpu_sim_insn = %lld\n", gpu_sim_insn); @@ -636,6 +712,8 @@ void gpgpu_sim::gpu_print_stat() const printf("gpu_tot_ipc = %12.4f\n", (float)(gpu_tot_sim_insn+gpu_sim_insn) / (gpu_tot_sim_cycle+gpu_sim_cycle)); printf("gpu_tot_issued_cta = %lld\n", gpu_tot_issued_cta); + + // performance counter for stalls due to congestion. printf("gpu_stall_dramfull = %d\n", gpu_stall_dramfull); printf("gpu_stall_icnt2sh = %d\n", gpu_stall_icnt2sh ); @@ -648,6 +726,9 @@ void gpgpu_sim::gpu_print_stat() const shader_print_l1_miss_stat( stdout ); m_shader_stats->print(stdout); +#ifdef GPGPUSIM_POWER_MODEL + m_gpgpusim_wrapper->print_power_kernel_stats(gpu_sim_cycle,gpu_tot_sim_cycle,gpu_tot_sim_insn + gpu_sim_insn ); +#endif // performance counter that are not local to one shader m_memory_stats->memlatstat_print(m_memory_config->m_n_mem,m_memory_config->nbk); @@ -664,8 +745,34 @@ void gpgpu_sim::gpu_print_stat() const StatDisp( g_inst_classification_stat[g_ptx_kernel_count]); StatDisp( g_inst_op_classification_stat[g_ptx_kernel_count]); } + +#ifdef GPGPUSIM_POWER_MODEL + m_gpgpusim_wrapper->detect_print_steady_state(1,gpu_tot_sim_insn+gpu_sim_insn); +#endif + + + // Interconnect power stat print + unsigned total_mem_to_simt=0; + unsigned total_simt_to_mem=0; + for (unsigned i=0;i<m_memory_config->m_n_mem;i++){ + unsigned temp=0; + m_memory_partition_unit[i]->set_icnt_power_stats(temp); + total_mem_to_simt += temp; + } + for(unsigned i=0; i<m_config.num_shader(); i++){ + unsigned temp=0; + m_cluster[i]->set_icnt_stats(temp); + total_simt_to_mem += temp; + } + printf("\nicnt_total_pkts_mem_to_simt=%u\n", total_mem_to_simt); + printf("icnt_total_pkts_simt_to_mem=%u\n\n", total_simt_to_mem); + time_vector_print(); fflush(stdout); + + + + } @@ -855,8 +962,13 @@ void gpgpu_sim::cycle() } if (clock_mask & DRAM) { - for (unsigned i=0;i<m_memory_config->m_n_mem;i++) - m_memory_partition_unit[i]->dram_cycle(); // Issue the dram command (scheduler + delay model) + for (unsigned i=0;i<m_memory_config->m_n_mem;i++){ + m_memory_partition_unit[i]->dram_cycle(); // Issue the dram command (scheduler + delay model) + // Update performance counters for DRAM + m_memory_partition_unit[i]->set_dram_power_stats(m_power_stats->pwr_mem_stat->n_cmd[0][i], m_power_stats->pwr_mem_stat->n_activity[0][i], + m_power_stats->pwr_mem_stat->n_nop[0][i], m_power_stats->pwr_mem_stat->n_act[0][i], m_power_stats->pwr_mem_stat->n_pre[0][i], + m_power_stats->pwr_mem_stat->n_rd[0][i], m_power_stats->pwr_mem_stat->n_wr[0][i], m_power_stats->pwr_mem_stat->n_req[0][i]); + } } // L2 operations follow L2 clock domain @@ -871,7 +983,11 @@ void gpgpu_sim::cycle() m_memory_partition_unit[i]->push( mf, gpu_sim_cycle + gpu_tot_sim_cycle ); } m_memory_partition_unit[i]->cache_cycle(gpu_sim_cycle+gpu_tot_sim_cycle); - } + m_memory_partition_unit[i]->set_L2cache_power_stats(m_power_stats->pwr_mem_stat->n_l2_read_access[0][i], m_power_stats->pwr_mem_stat->n_l2_read_miss[0][i], + m_power_stats->pwr_mem_stat->n_l2_write_access[0][i], m_power_stats->pwr_mem_stat->n_l2_write_miss[0][i]); + + m_memory_partition_unit[i]->set_icnt_power_stats(m_power_stats->pwr_mem_stat->n_mem_to_simt[0][i]); + } } if (clock_mask & ICNT) { @@ -883,26 +999,58 @@ void gpgpu_sim::cycle() for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { if (m_cluster[i]->get_not_completed() || get_more_cta_left() ) { m_cluster[i]->core_cycle(); + *active_sms+=m_cluster[i]->get_n_active_sms(); + + // Interconnect power stats: SIMT->MEM + m_cluster[i]->set_icnt_stats(m_power_stats->pwr_mem_stat->n_simt_to_mem[0][i]); } } + float temp=0; + for (unsigned i=0;i<m_shader_config->num_shader();i++){ + temp+=m_shader_stats->m_pipeline_duty_cycle[i]; + } + temp=temp/m_shader_config->num_shader(); + *average_pipeline_duty_cycle=((*average_pipeline_duty_cycle)+temp); + //cout<<"Average pipeline duty cycle: "<<*average_pipeline_duty_cycle<<endl; + + if( g_single_step && ((gpu_sim_cycle+gpu_tot_sim_cycle) >= g_single_step) ) { asm("int $03"); } gpu_sim_cycle++; if( g_interactive_debugger_enabled ) gpgpu_debug(); - + + // McPAT main cycle (interface with McPAT) +#ifdef GPGPUSIM_POWER_MODEL + if(m_config.g_power_simulation_enabled){ + mcpat_cycle(m_config, getShaderCoreConfig(), m_gpgpusim_wrapper, m_power_stats, m_config.gpu_stat_sample_freq, gpu_tot_sim_cycle, gpu_sim_cycle, gpu_tot_sim_insn, gpu_sim_insn); + } +#endif + issue_block2core(); - // Flush the caches once all of threads are completed. - if (m_config.gpgpu_flush_cache) { - int all_threads_complete = 1 ; + // Depending on configuration, flush the caches once all of threads are completed. + int all_threads_complete = 1; + if (m_config.gpgpu_flush_l1_cache) { for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { - if (m_cluster[i]->get_not_completed() == 0) - m_cluster[i]->cache_flush(); - else - all_threads_complete = 0 ; + if (m_cluster[i]->get_not_completed() == 0) + m_cluster[i]->cache_flush(); + else + all_threads_complete = 0 ; } + } + + if(m_config.gpgpu_flush_l2_cache){ + if(!m_config.gpgpu_flush_l1_cache){ + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { + if (m_cluster[i]->get_not_completed() != 0){ + all_threads_complete = 0 ; + break; + } + } + } + if (all_threads_complete && !m_memory_config->m_L2_config.disabled() ) { printf("Flushed L2 caches...\n"); if (m_memory_config->m_L2_config.get_num_lines()) { @@ -961,6 +1109,7 @@ void gpgpu_sim::cycle() } } + void shader_core_ctx::dump_warp_state( FILE *fout ) const { fprintf(fout, "\n"); diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h index d5b810f..7866688 100644 --- a/src/gpgpu-sim/gpu-sim.h +++ b/src/gpgpu-sim/gpu-sim.h @@ -32,10 +32,14 @@ #include "../abstract_hardware_model.h" #include "addrdec.h" #include "shader.h" +#include <iostream> +#include <fstream> #include <list> #include <stdio.h> + + // constants for statistics printouts #define GPU_RSTAT_SHD_INFO 0x1 #define GPU_RSTAT_BW_STAT 0x2 @@ -58,11 +62,90 @@ #define SAMPLELOG 222 #define DUMPLOG 333 + + + + enum dram_ctrl_t { DRAM_FIFO=0, DRAM_FRFCFS=1 }; + +struct power_config { + power_config() + { + m_valid = true; + } + void init() + { + + if (!g_power_simulation_enabled) + return; + + // initialize file name if it is not set + time_t curr_time; + time(&curr_time); + char *date = ctime(&curr_time); + char *s = date; + while (*s) { + if (*s == ' ' || *s == '\t' || *s == ':') *s = '-'; + if (*s == '\n' || *s == '\r' ) *s = 0; + s++; + } + char buf1[1024]; + snprintf(buf1,1024,"gpgpusim_power_report__%s.log",date); + g_power_filename = strdup(buf1); + char buf2[1024]; + snprintf(buf2,1024,"gpgpusim_power_trace_report__%s.log.gz",date); + g_power_trace_filename = strdup(buf2); + char buf3[1024]; + snprintf(buf3,1024,"gpgpusim_metric_trace_report__%s.log.gz",date); + g_metric_trace_filename = strdup(buf3); + char buf4[1024]; + snprintf(buf4,1024,"gpgpusim_steady_state_tracking_report__%s.log.gz",date); + g_steady_state_tracking_filename = strdup(buf4); + + if(g_steady_power_levels_enabled){ + sscanf(gpu_steady_state_definition,"%lf:%lf", &gpu_steady_power_deviation,&gpu_steady_min_period); + } + + //NOTE: After changing the nonlinear model to only scaling idle core, + //NOTE: The min_inc_per_active_sm is not used any more + if (g_use_nonlinear_model) + sscanf(gpu_nonlinear_model_config,"%lf:%lf", &gpu_idle_core_power,&gpu_min_inc_per_active_sm); + + } + void reg_options(class OptionParser * opp); + + char *g_power_config_name; + + bool m_valid; + bool g_power_simulation_enabled; + bool g_power_trace_enabled; + bool g_steady_power_levels_enabled; + bool g_power_per_cycle_dump; + bool g_power_simulator_debug; + char *g_power_filename; + char *g_power_trace_filename; + char *g_metric_trace_filename; + char * g_steady_state_tracking_filename; + int g_power_trace_zlevel; + char * gpu_steady_state_definition; + double gpu_steady_power_deviation; + double gpu_steady_min_period; + + //Nonlinear power model + bool g_use_nonlinear_model; + char * gpu_nonlinear_model_config; + double gpu_idle_core_power; + double gpu_min_inc_per_active_sm; + + +}; + + + struct memory_config { memory_config() { @@ -124,6 +207,7 @@ struct memory_config { m_address_mapping.init(m_n_mem); m_L2_config.init(); m_valid = true; + icnt_flit_size = 32; // Default 32 } void reg_options(class OptionParser * opp); @@ -172,10 +256,11 @@ struct memory_config { unsigned nbk; unsigned data_command_freq_ratio; // frequency ratio between DRAM data bus and command bus (2 for GDDR3, 4 for GDDR5) - unsigned dram_atom_size; // number of bytes transferred per read or write command linear_to_raw_address_translation m_address_mapping; + + unsigned icnt_flit_size; }; // global counters and flags (please try not to add to this list!!!) @@ -183,7 +268,7 @@ extern unsigned long long gpu_sim_cycle; extern unsigned long long gpu_tot_sim_cycle; extern bool g_interactive_debugger_enabled; -class gpgpu_sim_config : public gpgpu_functional_sim_config { +class gpgpu_sim_config : public power_config, public gpgpu_functional_sim_config { public: gpgpu_sim_config() { m_valid = false; } void reg_options(class OptionParser * opp); @@ -192,10 +277,12 @@ public: gpu_stat_sample_freq = 10000; gpu_runtime_stat_flag = 0; sscanf(gpgpu_runtime_stat, "%d:%x", &gpu_stat_sample_freq, &gpu_runtime_stat_flag); - m_shader_config.init(); + m_shader_config.init(); ptx_set_tex_cache_linesize(m_shader_config.m_L1T_config.get_line_sz()); m_memory_config.init(); init_clock_domains(); + power_config::init(); + // initialize file name if it is not set time_t curr_time; @@ -220,10 +307,10 @@ public: private: void init_clock_domains(void ); + bool m_valid; shader_core_config m_shader_config; memory_config m_memory_config; - // clock domains - frequency double core_freq; double icnt_freq; @@ -239,7 +326,8 @@ private: unsigned gpu_max_insn_opt; unsigned gpu_max_cta_opt; char *gpgpu_runtime_stat; - bool gpgpu_flush_cache; + bool gpgpu_flush_l1_cache; + bool gpgpu_flush_l2_cache; bool gpu_deadlock_detect; int gpgpu_dram_sched_queue_size; int gpgpu_cflog_interval; @@ -251,10 +339,14 @@ private: char *g_visualizer_filename; int g_visualizer_zlevel; + // statistics collection int gpu_stat_sample_freq; int gpu_runtime_stat_flag; + + + friend class gpgpu_sim; }; @@ -276,6 +368,8 @@ public: void update_stats(); void deadlock_check(); + void get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ); + int shared_mem_size() const; int num_registers_per_core() const; int wrp_size() const; @@ -288,7 +382,7 @@ public: kernel_info_t *select_kernel(); const gpgpu_sim_config &get_config() const { return m_config; } - void gpu_print_stat() const; + void gpu_print_stat(); void dump_pipeline( int mask, int s, int m ) const; //The next three functions added to be used by the functional simulation function @@ -313,12 +407,13 @@ public: */ simt_core_cluster * getSIMTCluster(); + private: // clocks void reinit_clock_domains(void); int next_clock_domain(void); void issue_block2core(); - + void print_dram_L2_stats(FILE *fout) const; void L2c_print_cache_stat() const; void shader_print_runtime_stat( FILE *fout ); void shader_print_l1_miss_stat( FILE *fout ) const; @@ -338,7 +433,8 @@ private: std::list<unsigned> m_finished_kernel; unsigned m_total_cta_launched; unsigned m_last_cluster_issue; - + float * average_pipeline_duty_cycle; + float * active_sms; // time of next rising edge double core_time; double icnt_time; @@ -358,14 +454,25 @@ private: // stats class shader_core_stats *m_shader_stats; class memory_stats_t *m_memory_stats; + class power_stat_t *m_power_stats; +#ifdef GPGPUSIM_POWER_MODEL + class gpgpu_sim_wrapper *m_gpgpusim_wrapper; +#endif unsigned long long gpu_tot_issued_cta; unsigned long long last_gpu_sim_insn; + + + public: unsigned long long gpu_sim_insn; unsigned long long gpu_tot_sim_insn; unsigned long long gpu_sim_insn_last_update; unsigned gpu_sim_insn_last_update_sid; + + + + }; #endif diff --git a/src/gpgpu-sim/icnt_wrapper.cc b/src/gpgpu-sim/icnt_wrapper.cc index 1c2ad86..f8c981d 100644 --- a/src/gpgpu-sim/icnt_wrapper.cc +++ b/src/gpgpu-sim/icnt_wrapper.cc @@ -34,6 +34,7 @@ icnt_push_p icnt_push; icnt_pop_p icnt_pop; icnt_transfer_p icnt_transfer; icnt_busy_p icnt_busy; +icnt_get_flit_size_p icnt_get_flit_size; int g_network_mode; char* g_network_config_filename; @@ -56,6 +57,7 @@ void icnt_init( unsigned int n_shader, unsigned int n_mem ) icnt_pop = interconnect_pop; icnt_transfer = advance_interconnect; icnt_busy = interconnect_busy; + icnt_get_flit_size = interconnect_get_flit_size; break; default: diff --git a/src/gpgpu-sim/icnt_wrapper.h b/src/gpgpu-sim/icnt_wrapper.h index 6c30bff..f8e6baf 100644 --- a/src/gpgpu-sim/icnt_wrapper.h +++ b/src/gpgpu-sim/icnt_wrapper.h @@ -37,6 +37,8 @@ typedef void* (*icnt_pop_p)(unsigned output); typedef void (*icnt_transfer_p)( ); typedef unsigned (*icnt_busy_p)( ); typedef void (*icnt_drain_p)( ); +typedef unsigned (*icnt_get_flit_size_p)(); + extern icnt_has_buffer_p icnt_has_buffer; extern icnt_push_p icnt_push; @@ -44,6 +46,7 @@ extern icnt_pop_p icnt_pop; extern icnt_transfer_p icnt_transfer; extern icnt_busy_p icnt_busy; extern icnt_drain_p icnt_drain; +extern icnt_get_flit_size_p icnt_get_flit_size; extern int g_network_mode; enum network_mode { diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index c03c47f..281da7f 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -109,6 +109,7 @@ void memory_partition_unit::cache_cycle( unsigned cycle ) mf->set_reply(); mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); m_L2_icnt_queue->push(mf); + n_mem_to_simt+=mf->get_num_flits(false); // Interconnect power stats (# of flits sent to the SMs) }else{ m_request_tracker.erase(mf); delete mf; @@ -127,6 +128,7 @@ void memory_partition_unit::cache_cycle( unsigned cycle ) mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); m_L2_icnt_queue->push(mf); m_dram_L2_queue->pop(); + n_mem_to_simt+=mf->get_num_flits(false); // Interconnect power stats (# of flits sent to the SMs) } } @@ -158,6 +160,7 @@ void memory_partition_unit::cache_cycle( unsigned cycle ) mf->set_reply(); mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); m_L2_icnt_queue->push(mf); + n_mem_to_simt+=mf->get_num_flits(false); // Interconnect power stats (# of flits sent to the SMs) } m_icnt_L2_queue->pop(); } else { @@ -221,24 +224,75 @@ void memory_partition_unit::print( FILE *fp ) const void memory_stats_t::print( FILE *fp ) { - fprintf(fp,"L2_write_miss = %d\n", L2_write_miss); - fprintf(fp,"L2_write_hit = %d\n", L2_write_hit); - fprintf(fp,"L2_read_miss = %d\n", L2_read_miss); - fprintf(fp,"L2_read_hit = %d\n", L2_read_hit); + + fprintf(fp,"gpgpu_l2_write_miss = %d\n", L2_write_miss); + fprintf(fp,"gpgpu_l2_write_access = %d\n", L2_write_access); + fprintf(fp,"gpgpu_l2_read_miss = %d\n", L2_read_miss); + fprintf(fp,"gpgpu_l2_read_access = %d\n", L2_read_access); + } void memory_stats_t::visualizer_print( gzFile visualizer_file ) { gzprintf(visualizer_file, "Ltwowritemiss: %d\n", L2_write_miss); - gzprintf(visualizer_file, "Ltwowritehit: %d\n", L2_write_hit); + gzprintf(visualizer_file, "Ltwowritehit: %d\n", L2_write_access-L2_write_miss); gzprintf(visualizer_file, "Ltworeadmiss: %d\n", L2_read_miss); - gzprintf(visualizer_file, "Ltworeadhit: %d\n", L2_read_hit); - signed long long average_mf_latency = 0; - if (mf_num_lat_pw) - average_mf_latency = mf_tot_lat_pw / mf_num_lat_pw; - gzprintf(visualizer_file, "averagemflatency: %lld\n", average_mf_latency); + gzprintf(visualizer_file, "Ltworeadhit: %d\n", L2_read_access-L2_read_miss); + if (num_mfs) + gzprintf(visualizer_file, "averagemflatency: %lld\n", mf_total_lat/num_mfs); } +void gpgpu_sim::print_dram_L2_stats(FILE *fout) const +{ + + unsigned cmd=0; + unsigned activity=0; + unsigned nop=0; + unsigned act=0; + unsigned pre=0; + unsigned rd=0; + unsigned wr=0; + unsigned req=0; + unsigned l2_read_access=0; + unsigned l2_read_miss=0; + unsigned l2_write_access=0; + unsigned l2_write_miss=0; + unsigned tot_cmd=0; + unsigned tot_nop=0; + unsigned tot_act=0; + unsigned tot_pre=0; + unsigned tot_rd=0; + unsigned tot_wr=0; + unsigned tot_req=0; + unsigned tot_l2_read_access=0; + unsigned tot_l2_read_miss=0; + unsigned tot_l2_write_access=0; + unsigned tot_l2_write_miss=0; + + for (unsigned i=0;i<m_memory_config->m_n_mem;i++){ + m_memory_partition_unit[i]->set_dram_power_stats(cmd,activity,nop,act,pre,rd,wr,req); + m_memory_partition_unit[i]->set_L2cache_power_stats(l2_read_access,l2_read_miss,l2_write_access,l2_write_miss); + tot_cmd+=cmd; + tot_nop+=nop; + tot_act+=act; + tot_pre+=pre; + tot_rd+=rd; + tot_wr+=wr; + tot_req+=req; + tot_l2_read_access+=l2_read_access; + tot_l2_read_miss+=l2_read_miss; + tot_l2_write_access+=l2_write_access; + tot_l2_write_miss+=l2_write_miss; + } + fprintf(fout,"gpgpu_n_l2_cache_read_access = %d\n",tot_l2_read_access ); + fprintf(fout,"gpgpu_n_l2_cache_read_miss = %d\n",tot_l2_read_miss ); + fprintf(fout,"gpgpu_n_l2_cache_write_access = %d\n",tot_l2_write_access ); + fprintf(fout,"gpgpu_n_l2_cache_write_miss = %d\n",tot_l2_write_miss ); + fprintf(fout,"gpgpu_n_dram_reads = %d\n",tot_rd ); + fprintf(fout,"gpgpu_n_dram_writes = %d\n",tot_wr ); + fprintf(fout,"gpgpu_n_dram_activate = %d\n",tot_act ); + +} void gpgpu_sim::L2c_print_cache_stat() const { unsigned i, j, k; @@ -341,3 +395,25 @@ void memory_partition_unit::dram_cycle() m_dram->push(mf); } } + +void memory_partition_unit::set_dram_power_stats(unsigned &n_cmd, + unsigned &n_activity, + unsigned &n_nop, + unsigned &n_act, + unsigned &n_pre, + unsigned &n_rd, + unsigned &n_wr, + unsigned &n_req) const{ + m_dram->set_dram_power_stats(n_cmd, n_activity, n_nop, n_act, n_pre, n_rd, n_wr, n_req); +} + +void memory_partition_unit::set_L2cache_power_stats(unsigned &n_read_access, + unsigned &n_read_miss, + unsigned &n_write_access, + unsigned &n_write_miss) const{ + m_L2cache->get_data_stats(n_read_access,n_read_miss,n_write_access,n_write_miss); +} + +void memory_partition_unit::set_icnt_power_stats(unsigned &mem_to_simt) const{ + mem_to_simt = n_mem_to_simt; +} diff --git a/src/gpgpu-sim/l2cache.h b/src/gpgpu-sim/l2cache.h index c2c624f..3b25565 100644 --- a/src/gpgpu-sim/l2cache.h +++ b/src/gpgpu-sim/l2cache.h @@ -77,6 +77,24 @@ public: void visualize() const { m_dram->visualize(); } void print( FILE *fp ) const; + + // Power model + void set_dram_power_stats(unsigned &n_cmd, + unsigned &n_activity, + unsigned &n_nop, + unsigned &n_act, + unsigned &n_pre, + unsigned &n_rd, + unsigned &n_wr, + unsigned &n_req) const; + + void set_L2cache_power_stats(unsigned &n_read_access, + unsigned &n_read_miss, + unsigned &n_write_access, + unsigned &n_write_miss) const; + + void set_icnt_power_stats(unsigned &n_mem_to_simt) const; + private: // data unsigned m_id; @@ -116,6 +134,9 @@ private: std::set<mem_fetch*> m_request_tracker; friend class L2interface; + + // interconnect power stats + unsigned n_mem_to_simt; }; class L2interface : public mem_fetch_interface { diff --git a/src/gpgpu-sim/mem_fetch.cc b/src/gpgpu-sim/mem_fetch.cc index 97721c0..1de10a5 100644 --- a/src/gpgpu-sim/mem_fetch.cc +++ b/src/gpgpu-sim/mem_fetch.cc @@ -60,6 +60,7 @@ mem_fetch::mem_fetch( const mem_access_t &access, m_status = MEM_FETCH_INITIALIZED; m_status_change = gpu_sim_cycle + gpu_tot_sim_cycle; m_mem_config = config; + icnt_flit_size = config->icnt_flit_size; } mem_fetch::~mem_fetch() @@ -119,3 +120,17 @@ bool mem_fetch::isconst() const if( m_inst.empty() ) return false; return (m_inst.space.get_type() == const_space) || (m_inst.space.get_type() == param_space_kernel); } + +/// Returns number of flits traversing interconnect. simt_to_mem specifies the direction +unsigned mem_fetch::get_num_flits(bool simt_to_mem){ + unsigned sz=0; + if( (simt_to_mem && get_is_write()) || !(simt_to_mem || get_is_write()) ) + sz = size(); + else + sz = get_ctrl_size(); + + return (sz/icnt_flit_size) + ( (sz % icnt_flit_size)? 1:0); +} + + + diff --git a/src/gpgpu-sim/mem_fetch.h b/src/gpgpu-sim/mem_fetch.h index 501d52a..c4ba0dc 100644 --- a/src/gpgpu-sim/mem_fetch.h +++ b/src/gpgpu-sim/mem_fetch.h @@ -79,6 +79,8 @@ public: void set_data_size( unsigned size ) { m_data_size=size; } unsigned get_ctrl_size() const { return m_ctrl_size; } unsigned size() const { return m_data_size+m_ctrl_size; } + bool is_write() {return m_access.is_write();} + void set_addr(new_addr_type addr) { m_access.set_addr(addr); } new_addr_type get_addr() const { return m_access.get_addr(); } new_addr_type get_partition_addr() const { return m_partition_addr; } bool get_is_write() const { return m_access.is_write(); } @@ -100,11 +102,14 @@ public: enum mem_access_type get_access_type() const { return m_access.get_type(); } const active_mask_t& get_access_warp_mask() const { return m_access.get_warp_mask(); } mem_access_byte_mask_t get_access_byte_mask() const { return m_access.get_byte_mask(); } + address_type get_pc() const { return m_inst.empty()?-1:m_inst.pc; } const warp_inst_t &get_inst() { return m_inst; } enum mem_fetch_status get_status() const { return m_status; } const memory_config *get_mem_config(){return m_mem_config;} + + unsigned get_num_flits(bool simt_to_mem); private: // request source information unsigned m_request_uid; @@ -135,6 +140,7 @@ private: static unsigned sm_next_mf_request_uid; const class memory_config *m_mem_config; + unsigned icnt_flit_size; }; #endif diff --git a/src/gpgpu-sim/mem_fetch_status.tup b/src/gpgpu-sim/mem_fetch_status.tup index 328d517..b4d4e7a 100644 --- a/src/gpgpu-sim/mem_fetch_status.tup +++ b/src/gpgpu-sim/mem_fetch_status.tup @@ -31,7 +31,7 @@ MF_TUP_BEGIN( mem_fetch_status ) MF_TUP( IN_L1D_MISS_QUEUE ), MF_TUP( IN_L1T_MISS_QUEUE ), MF_TUP( IN_L1C_MISS_QUEUE ), - MF_TUP( IN_TLB_MISS_QUEUE ), + MF_TUP( IN_L1TLB_MISS_QUEUE ), MF_TUP( IN_VM_MANAGER_QUEUE ), MF_TUP( IN_ICNT_TO_MEM ), MF_TUP( IN_PARTITION_ROP_DELAY ), diff --git a/src/gpgpu-sim/mem_latency_stat.cc b/src/gpgpu-sim/mem_latency_stat.cc index aed76aa..b86c652 100644 --- a/src/gpgpu-sim/mem_latency_stat.cc +++ b/src/gpgpu-sim/mem_latency_stat.cc @@ -66,7 +66,9 @@ memory_stats_t::memory_stats_t( unsigned n_shader, const struct shader_core_conf m_n_shader=n_shader; m_memory_config=mem_config; - + total_n_access=0; + total_n_reads=0; + total_n_writes=0; max_mrq_latency = 0; max_dq_latency = 0; max_mf_latency = 0; @@ -123,8 +125,8 @@ memory_stats_t::memory_stats_t( unsigned n_shader, const struct shader_core_conf } L2_write_miss=0; - L2_write_hit=0; - L2_read_hit=0; + L2_write_access=0; + L2_read_access=0; L2_read_miss=0; L2_cbtoL2length = (unsigned int*) calloc(mem_config->m_n_mem, sizeof(unsigned int)); L2_cbtoL2writelength = (unsigned int*) calloc(mem_config->m_n_mem, sizeof(unsigned int)); diff --git a/src/gpgpu-sim/mem_latency_stat.h b/src/gpgpu-sim/mem_latency_stat.h index 95017d8..83114fa 100644 --- a/src/gpgpu-sim/mem_latency_stat.h +++ b/src/gpgpu-sim/mem_latency_stat.h @@ -82,9 +82,9 @@ public: // stats + unsigned L2_write_access; unsigned L2_write_miss; - unsigned L2_write_hit; - unsigned L2_read_hit; + unsigned L2_read_access; unsigned L2_read_miss; unsigned int *L2_cbtoL2length; unsigned int *L2_cbtoL2writelength; @@ -98,6 +98,11 @@ public: unsigned int **row_access; //row_access[dram chip id][bank id] unsigned int **max_conc_access2samerow; //max_conc_access2samerow[dram chip id][bank id] unsigned int **max_servicetime2samerow; //max_servicetime2samerow[dram chip id][bank id] + + // Power stats + unsigned total_n_access; + unsigned total_n_reads; + unsigned total_n_writes; }; #endif /*MEM_LATENCY_STAT_H*/ diff --git a/src/gpgpu-sim/power_interface.cc b/src/gpgpu-sim/power_interface.cc new file mode 100644 index 0000000..4f8daca --- /dev/null +++ b/src/gpgpu-sim/power_interface.cc @@ -0,0 +1,125 @@ +// Copyright (c) 2009-2011, Tor M. Aamodt, Ahmed El-Shafiey, Tayler Hetherington +// The University of British Columbia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// Neither the name of The University of British Columbia nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "power_interface.h" + +void init_mcpat(const gpgpu_sim_config &config, class gpgpu_sim_wrapper *wrapper, unsigned stat_sample_freq, unsigned tot_inst, unsigned inst){ + + wrapper->init_mcpat(config.g_power_config_name, config.g_power_filename, config.g_power_trace_filename, + config.g_metric_trace_filename,config.g_steady_state_tracking_filename,config.g_power_simulation_enabled, + config.g_power_trace_enabled,config.g_steady_power_levels_enabled,config.g_power_per_cycle_dump, + config.gpu_steady_power_deviation,config.gpu_steady_min_period,config.g_power_trace_zlevel, + tot_inst+inst,stat_sample_freq + ); + +} + +void mcpat_cycle(const gpgpu_sim_config &config, const struct shader_core_config *shdr_config, class gpgpu_sim_wrapper *wrapper, class power_stat_t *power_stats, unsigned stat_sample_freq, unsigned tot_cycle, unsigned cycle, unsigned tot_inst, unsigned inst){ + + static bool mcpat_init=true; + + if(mcpat_init){ // If first cycle, don't have any power numbers yet + mcpat_init=false; + return; + } + + if ((tot_cycle+cycle) % stat_sample_freq == 0) { + + wrapper->set_inst_power(shdr_config->gpgpu_clock_gated_lanes, + stat_sample_freq, stat_sample_freq, + power_stats->get_total_inst(), power_stats->get_total_int_inst(), + power_stats->get_total_fp_inst(), power_stats->get_l1d_read_accesses(), + power_stats->get_l1d_write_accesses(), power_stats->get_committed_inst()); + + // Single RF for both int and fp ops + wrapper->set_regfile_power(power_stats->get_regfile_reads(), power_stats->get_regfile_writes(), power_stats->get_non_regfile_operands()); + + //Instruction cache stats + wrapper->set_icache_power(power_stats->get_inst_c_hits(), power_stats->get_inst_c_misses()); + + //Constant Cache, shared memory, texture cache + wrapper->set_ccache_power(power_stats->get_constant_c_hits(), power_stats->get_constant_c_misses()); + wrapper->set_tcache_power(power_stats->get_texture_c_hits(), power_stats->get_texture_c_misses()); + wrapper->set_shrd_mem_power(power_stats->get_shmem_read_access()); + + wrapper->set_l1cache_power(power_stats->get_l1d_read_hits(), power_stats->get_l1d_read_misses(), + power_stats->get_l1d_write_hits(), power_stats->get_l1d_write_misses()); + + + wrapper->set_l2cache_power(power_stats->get_l2_read_hits(), power_stats->get_l2_read_misses(), + power_stats->get_l2_write_hits(), power_stats->get_l2_write_misses()); + + + float active_sms=(*power_stats->m_active_sms)/stat_sample_freq; + float num_cores = shdr_config->num_shader(); + float num_idle_core = num_cores - active_sms; + wrapper->set_idle_core_power(num_idle_core); + + //pipeline power - pipeline_duty_cycle *= percent_active_sms; + float pipeline_duty_cycle=((*power_stats->m_average_pipeline_duty_cycle/( stat_sample_freq)) < 0.8)?((*power_stats->m_average_pipeline_duty_cycle)/stat_sample_freq):0.8; + wrapper->set_duty_cycle_power(pipeline_duty_cycle); + + //Memory Controller + wrapper->set_mem_ctrl_power(power_stats->get_dram_rd(), power_stats->get_dram_wr(), power_stats->get_dram_pre()); + + //Execution pipeline accesses + //FPU (SP) accesses, Integer ALU (not present in Tesla), Sfu accesses + wrapper->set_exec_unit_power(power_stats->get_tot_fpu_accessess(), power_stats->get_ialu_accessess(), power_stats->get_tot_sfu_accessess()); + + //Average active lanes for sp and sfu pipelines + float avg_sp_active_lanes=(power_stats->get_sp_active_lanes())/stat_sample_freq; + float avg_sfu_active_lanes=(power_stats->get_sfu_active_lanes())/stat_sample_freq; + assert(avg_sp_active_lanes<=32); + assert(avg_sfu_active_lanes<=32); + wrapper->set_active_lanes_power((power_stats->get_sp_active_lanes())/stat_sample_freq, + (power_stats->get_sfu_active_lanes())/stat_sample_freq); + + + //NoC stats (32/4)--> Number of 32 bit words in 32B block + //unsigned l2cache_tot_access = power_stats->get_l2_read_accesses() + power_stats->get_l2_write_accesses(); + unsigned n_icnt_simt_to_mem = power_stats->get_icnt_simt_to_mem(); // # flits from SIMT clusters to memory partitions + unsigned n_icnt_mem_to_simt = power_stats->get_icnt_mem_to_simt(); // # flits from memory partitions to SIMT clusters + //wrapper->set_NoC_power((double)(n_icnt_mem_to_simt + n_icnt_simt_to_mem)); // Number of flits traversing the interconnect + wrapper->set_NoC_power(n_icnt_mem_to_simt, n_icnt_simt_to_mem); // Number of flits traversing the interconnect + + wrapper->compute(); + + + wrapper->update_components_power(); + wrapper->print_trace_files(); + power_stats->save_stats(); + + wrapper->detect_print_steady_state(0,tot_inst+inst); + + wrapper->power_metrics_calculations(); + + + wrapper->dump(); + } + //wrapper->close_files(); +} + diff --git a/src/gpgpu-sim/power_interface.h b/src/gpgpu-sim/power_interface.h new file mode 100644 index 0000000..3033743 --- /dev/null +++ b/src/gpgpu-sim/power_interface.h @@ -0,0 +1,43 @@ +// Copyright (c) 2009-2011, Tor M. Aamodt, Ahmed El-Shafiey, Tayler Hetherington +// The University of British Columbia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// Neither the name of The University of British Columbia nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef POWER_INTERFACE_H_ +#define POWER_INTERFACE_H_ + +#include "gpu-sim.h" +#include "power_stat.h" +#include "shader.h" + + +#include "gpgpu_sim_wrapper.h" + +void init_mcpat(const gpgpu_sim_config &config, class gpgpu_sim_wrapper *wrapper, unsigned stat_sample_freq, unsigned tot_inst, unsigned inst); +void mcpat_cycle(const gpgpu_sim_config &config, const struct shader_core_config *shdr_config, class gpgpu_sim_wrapper *wrapper, class power_stat_t *power_stats, + unsigned stat_sample_freq, unsigned tot_cycle, unsigned cycle, unsigned tot_inst, unsigned inst); + + +#endif /* POWER_INTERFACE_H_ */ diff --git a/src/gpgpu-sim/power_stat.cc b/src/gpgpu-sim/power_stat.cc new file mode 100644 index 0000000..e1f4f8a --- /dev/null +++ b/src/gpgpu-sim/power_stat.cc @@ -0,0 +1,335 @@ +// Copyright (c) 2009-2011, Tor M. Aamodt, Ahmed El-Shafiey, Tayler Hetherington +// The University of British Columbia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// Neither the name of The University of British Columbia nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "../abstract_hardware_model.h" +#include "power_stat.h" +#include "gpu-sim.h" +#include "gpu-misc.h" +#include "shader.h" +#include "mem_fetch.h" +#include "stat-tool.h" +#include "../cuda-sim/ptx-stats.h" +#include "visualizer.h" +#include "dram.h" + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + + + +power_mem_stat_t::power_mem_stat_t(const struct memory_config *mem_config, const struct shader_core_config *shdr_config, memory_stats_t *mem_stats, shader_core_stats *shdr_stats){ + assert( mem_config->m_valid ); + m_mem_stats = mem_stats; + m_config = mem_config; + m_core_stats = shdr_stats; + m_core_config = shdr_config; + + init(); +} + +void power_mem_stat_t::init(){ + inst_c_read_access[0] = m_core_stats->inst_c_read_access; + inst_c_read_miss[0] = m_core_stats->inst_c_read_miss; + const_c_read_access[0] = m_core_stats->const_c_read_access; + const_c_read_miss[0] = m_core_stats->const_c_read_miss; + text_c_read_access[0] = m_core_stats->text_c_read_access; + text_c_read_miss[0] = m_core_stats->text_c_read_miss; + l1d_read_access[0] = m_core_stats->l1d_read_access; + l1d_read_miss[0] = m_core_stats->l1d_read_miss; + l1d_write_access[0] = m_core_stats->l1d_write_access; + l1d_write_miss[0] = m_core_stats->l1d_write_miss; + + shmem_read_access[0] = m_core_stats->gpgpu_n_shmem_bank_access; // Shared memory access + + inst_c_read_access[1] = (unsigned *)calloc(m_core_config->num_shader(),sizeof(unsigned)); + inst_c_read_miss[1] = (unsigned *)calloc(m_core_config->num_shader(),sizeof(unsigned)); + const_c_read_access[1] = (unsigned *)calloc(m_core_config->num_shader(),sizeof(unsigned)); + const_c_read_miss[1] = (unsigned *)calloc(m_core_config->num_shader(),sizeof(unsigned)); + text_c_read_access[1] = (unsigned *)calloc(m_core_config->num_shader(),sizeof(unsigned)); + text_c_read_miss[1] = (unsigned *)calloc(m_core_config->num_shader(),sizeof(unsigned)); + l1d_read_access[1] = (unsigned *)calloc(m_core_config->num_shader(),sizeof(unsigned)); + l1d_read_miss[1] = (unsigned *)calloc(m_core_config->num_shader(),sizeof(unsigned)); + l1d_write_access[1] = (unsigned *)calloc(m_core_config->num_shader(),sizeof(unsigned)); + l1d_write_miss[1] = (unsigned *)calloc(m_core_config->num_shader(),sizeof(unsigned)); + + shmem_read_access[1] = (unsigned *)calloc(m_core_config->num_shader(),sizeof(unsigned)); + + // Low-level DRAM/L2-cache stats + for(unsigned i=0; i<2; ++i){ + n_l2_read_access[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_l2_read_miss[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_l2_write_access[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_l2_write_miss[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_cmd[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_activity[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_nop[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_act[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_pre[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_rd[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_wr[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_req[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + + // Interconnect stats + n_mem_to_simt[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); // Counted at memory partition + n_simt_to_mem[i] = (unsigned *)calloc(m_core_config->num_shader(),sizeof(unsigned)); // Counted at SM + } +} + +void power_mem_stat_t::save_stats(){ + for(unsigned i=0; i<m_core_config->num_shader(); ++i){ + inst_c_read_access[1][i] = inst_c_read_access[0][i] ; + inst_c_read_miss[1][i] = inst_c_read_miss[0][i] ; + const_c_read_access[1][i] = const_c_read_access[0][i] ; + const_c_read_miss[1][i] = const_c_read_miss[0][i] ; + text_c_read_access[1][i] = text_c_read_access[0][i] ; + text_c_read_miss[1][i] = text_c_read_miss[0][i] ; + l1d_read_access[1][i] = l1d_read_access[0][i] ; + l1d_read_miss[1][i] = l1d_read_miss[0][i] ; + l1d_write_access[1][i] = l1d_write_access[0][i] ; + l1d_write_miss[1][i] = l1d_write_miss[0][i] ; + shmem_read_access[1][i] = shmem_read_access[0][i] ; // Shared memory access + + n_simt_to_mem[1][i] = n_simt_to_mem[0][i]; // Interconnect + } + + for(unsigned i=0; i<m_config->m_n_mem; ++i){ + n_l2_read_access[1][i] = n_l2_read_access[0][i]; + n_l2_read_miss[1][i] = n_l2_read_miss[0][i]; + n_l2_write_access[1][i] = n_l2_write_access[0][i]; + n_l2_write_miss[1][i] = n_l2_write_miss[0][i]; + n_cmd[1][i] = n_cmd[0][i]; + n_activity[1][i] = n_activity[0][i]; + n_nop[1][i] = n_nop[0][i]; + n_act[1][i] = n_act[0][i]; + n_pre[1][i] = n_pre[0][i]; + n_rd[1][i] = n_rd[0][i]; + n_wr[1][i] = n_wr[0][i]; + n_req[1][i] = n_req[0][i]; + + n_mem_to_simt[1][i] = n_mem_to_simt[0][i]; // Interconnect + } +} + +void power_mem_stat_t::visualizer_print( gzFile power_visualizer_file ){ + +} + +void power_mem_stat_t::print (FILE *fout) const { + fprintf(fout, "\n\n==========Power Metrics -- Memory==========\n"); + unsigned total_mem_reads=0; + unsigned total_mem_writes=0; + for(unsigned i=0; i<m_config->m_n_mem; ++i){ + total_mem_reads += n_rd[0][i]; + total_mem_writes += n_wr[0][i]; + } + fprintf(fout, "Total memory controller accesses: %u\n", total_mem_reads+total_mem_writes); + fprintf(fout, "Total memory controller reads: %u\n", total_mem_reads); + fprintf(fout, "Total memory controller writes: %u\n", total_mem_writes); + for(unsigned i=0; i<m_core_config->num_shader(); ++i){ + fprintf(fout, "Shader core %d\n", i); + fprintf(fout, "\tTotal instruction cache access: %u\n", inst_c_read_access[0][i]); + fprintf(fout, "\tTotal instruction cache miss: %u\n", inst_c_read_miss[0][i]); + fprintf(fout, "\tTotal constant cache access: %u\n", const_c_read_access[0][i]); + fprintf(fout, "\tTotal constant cache miss: %u\n", const_c_read_miss[0][i]); + fprintf(fout, "\tTotal texture cache access: %u\n", text_c_read_access[0][i]); + fprintf(fout, "\tTotal texture cache miss: %u\n", text_c_read_miss[0][i]); + fprintf(fout, "\tTotal l1d read access: %u\n", l1d_read_access[0][i]); + fprintf(fout, "\tTotal l1d read miss: %u\n", l1d_read_miss[0][i]); + fprintf(fout, "\tTotal l1d write access: %u\n", l1d_write_access[0][i]); + fprintf(fout, "\tTotal l1d write miss: %u\n", l1d_write_miss[0][i]); + fprintf(fout, "\tTotal shared memory access: %u\n", shmem_read_access[0][i]); + } +} + + +power_core_stat_t::power_core_stat_t( const struct shader_core_config *shader_config, shader_core_stats *core_stats ) +{ + assert( shader_config->m_valid ); + m_config = shader_config; + shader_core_power_stats_pod *pod = this; + memset(pod,0,sizeof(shader_core_power_stats_pod)); + m_core_stats=core_stats; + + init(); + +} + +void power_core_stat_t::visualizer_print( gzFile visualizer_file ) +{ + +} + +void power_core_stat_t::print (FILE *fout) +{ + // per core statistics + fprintf(fout,"Power Metrics: \n"); + for(unsigned i=0; i<m_config->num_shader();i++){ + fprintf(fout,"core %u:\n",i); + fprintf(fout,"\tpipeline duty cycle =%f\n",m_pipeline_duty_cycle[0][i]); + fprintf(fout,"\tTotal Deocded Instructions=%u\n",m_num_decoded_insn[0][i]); + fprintf(fout,"\tTotal FP Deocded Instructions=%u\n",m_num_FPdecoded_insn[0][i]); + fprintf(fout,"\tTotal INT Deocded Instructions=%u\n",m_num_INTdecoded_insn[0][i]); + fprintf(fout,"\tTotal LOAD Queued Instructions=%u\n",m_num_loadqueued_insn[0][i]); + fprintf(fout,"\tTotal STORE Queued Instructions=%u\n",m_num_storequeued_insn[0][i]); + fprintf(fout,"\tTotal IALU Acesses=%u\n",m_num_ialu_acesses[0][i]); + fprintf(fout,"\tTotal FP Acesses=%u\n",m_num_fp_acesses[0][i]); + fprintf(fout,"\tTotal IMUL Acesses=%u\n",m_num_imul_acesses[0][i]); + fprintf(fout,"\tTotal IMUL24 Acesses=%u\n",m_num_imul24_acesses[0][i]); + fprintf(fout,"\tTotal IMUL32 Acesses=%u\n",m_num_imul32_acesses[0][i]); + fprintf(fout,"\tTotal IDIV Acesses=%u\n",m_num_idiv_acesses[0][i]); + fprintf(fout,"\tTotal FPMUL Acesses=%u\n",m_num_fpmul_acesses[0][i]); + fprintf(fout,"\tTotal SFU Acesses=%u\n",m_num_trans_acesses[0][i]); + fprintf(fout,"\tTotal FPDIV Acesses=%u\n",m_num_fpdiv_acesses[0][i]); + fprintf(fout,"\tTotal SFU Acesses=%u\n",m_num_sfu_acesses[0][i]); + fprintf(fout,"\tTotal SP Acesses=%u\n",m_num_sp_acesses[0][i]); + fprintf(fout,"\tTotal MEM Acesses=%u\n",m_num_mem_acesses[0][i]); + fprintf(fout,"\tTotal SFU Commissions=%u\n",m_num_sfu_committed[0][i]); + fprintf(fout,"\tTotal SP Commissions=%u\n",m_num_sp_committed[0][i]); + fprintf(fout,"\tTotal MEM Commissions=%u\n",m_num_mem_committed[0][i]); + fprintf(fout,"\tTotal REG Reads=%u\n",m_read_regfile_acesses[0][i]); + fprintf(fout,"\tTotal REG Writes=%u\n",m_write_regfile_acesses[0][i]); + fprintf(fout,"\tTotal NON REG=%u\n",m_non_rf_operands[0][i]); + } +} +void power_core_stat_t::init() +{ + m_pipeline_duty_cycle[0]=m_core_stats->m_pipeline_duty_cycle; + m_num_decoded_insn[0]=m_core_stats->m_num_decoded_insn; + m_num_FPdecoded_insn[0]=m_core_stats->m_num_FPdecoded_insn; + m_num_INTdecoded_insn[0]=m_core_stats->m_num_INTdecoded_insn; + m_num_storequeued_insn[0]=m_core_stats->m_num_storequeued_insn; + m_num_loadqueued_insn[0]=m_core_stats->m_num_loadqueued_insn; + m_num_ialu_acesses[0]=m_core_stats->m_num_ialu_acesses; + m_num_fp_acesses[0]=m_core_stats->m_num_fp_acesses; + m_num_imul_acesses[0]=m_core_stats->m_num_imul_acesses; + m_num_imul24_acesses[0]=m_core_stats->m_num_imul24_acesses; + m_num_imul32_acesses[0]=m_core_stats->m_num_imul32_acesses; + m_num_fpmul_acesses[0]=m_core_stats->m_num_fpmul_acesses; + m_num_idiv_acesses[0]=m_core_stats->m_num_idiv_acesses; + m_num_fpdiv_acesses[0]=m_core_stats->m_num_fpdiv_acesses; + m_num_sp_acesses[0]=m_core_stats->m_num_sp_acesses; + m_num_sfu_acesses[0]=m_core_stats->m_num_sfu_acesses; + m_num_trans_acesses[0]=m_core_stats->m_num_trans_acesses; + m_num_mem_acesses[0]=m_core_stats->m_num_mem_acesses; + m_num_sp_committed[0]=m_core_stats->m_num_sp_committed; + m_num_sfu_committed[0]=m_core_stats->m_num_sfu_committed; + m_num_mem_committed[0]=m_core_stats->m_num_mem_committed; + m_read_regfile_acesses[0]=m_core_stats->m_read_regfile_acesses; + m_write_regfile_acesses[0]=m_core_stats->m_write_regfile_acesses; + m_non_rf_operands[0]=m_core_stats->m_non_rf_operands; + m_active_sp_lanes[0]=m_core_stats->m_active_sp_lanes; + m_active_sfu_lanes[0]=m_core_stats->m_active_sfu_lanes; + m_num_tex_inst[0]=m_core_stats->m_num_tex_inst; + + + m_pipeline_duty_cycle[1]=(float*)calloc(m_config->num_shader(),sizeof(float)); + m_num_decoded_insn[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_FPdecoded_insn[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_INTdecoded_insn[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_storequeued_insn[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_loadqueued_insn[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_ialu_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_fp_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_tex_inst[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_imul_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_imul24_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_imul32_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_fpmul_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_idiv_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_fpdiv_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_sp_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_sfu_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_trans_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_mem_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_sp_committed[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_sfu_committed[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_mem_committed[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_read_regfile_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_write_regfile_acesses[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_non_rf_operands[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_active_sp_lanes[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_active_sfu_lanes[1]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); +} + +void power_core_stat_t::save_stats(){ + for(unsigned i=0; i<m_config->num_shader(); ++i){ + m_pipeline_duty_cycle[1][i]=m_pipeline_duty_cycle[0][i]; + m_num_decoded_insn[1][i]= m_num_decoded_insn[0][i]; + m_num_FPdecoded_insn[1][i]=m_num_FPdecoded_insn[0][i]; + m_num_INTdecoded_insn[1][i]=m_num_INTdecoded_insn[0][i]; + m_num_storequeued_insn[1][i]=m_num_storequeued_insn[0][i]; + m_num_loadqueued_insn[1][i]=m_num_loadqueued_insn[0][i]; + m_num_ialu_acesses[1][i]=m_num_ialu_acesses[0][i]; + m_num_fp_acesses[1][i]=m_num_fp_acesses[0][i]; + m_num_tex_inst[1][i]=m_num_tex_inst[0][i]; + m_num_imul_acesses[1][i]=m_num_imul_acesses[0][i]; + m_num_imul24_acesses[1][i]=m_num_imul24_acesses[0][i]; + m_num_imul32_acesses[1][i]=m_num_imul32_acesses[0][i]; + m_num_fpmul_acesses[1][i]=m_num_fpmul_acesses[0][i]; + m_num_idiv_acesses[1][i]=m_num_idiv_acesses[0][i]; + m_num_fpdiv_acesses[1][i]=m_num_fpdiv_acesses[0][i]; + m_num_sp_acesses[1][i]=m_num_sp_acesses[0][i]; + m_num_sfu_acesses[1][i]=m_num_sfu_acesses[0][i]; + m_num_trans_acesses[1][i]=m_num_trans_acesses[0][i]; + m_num_mem_acesses[1][i]=m_num_mem_acesses[0][i]; + m_num_sp_committed[1][i]=m_num_sp_committed[0][i]; + m_num_sfu_committed[1][i]=m_num_sfu_committed[0][i]; + m_num_mem_committed[1][i]=m_num_mem_committed[0][i]; + m_read_regfile_acesses[1][i]=m_read_regfile_acesses[0][i]; + m_write_regfile_acesses[1][i]=m_write_regfile_acesses[0][i]; + m_non_rf_operands[1][i]=m_non_rf_operands[0][i]; + m_active_sp_lanes[1][i]=m_active_sp_lanes[0][i]; + m_active_sfu_lanes[1][i]=m_active_sfu_lanes[0][i]; + } +} + +power_stat_t::power_stat_t( const struct shader_core_config *shader_config,float * average_pipeline_duty_cycle,float *active_sms,shader_core_stats * shader_stats, const struct memory_config *mem_config,memory_stats_t * memory_stats) +{ + assert( shader_config->m_valid ); + assert( mem_config->m_valid ); + pwr_core_stat= new power_core_stat_t(shader_config,shader_stats); + pwr_mem_stat= new power_mem_stat_t(mem_config,shader_config, memory_stats, shader_stats); + m_average_pipeline_duty_cycle=average_pipeline_duty_cycle; + m_active_sms=active_sms; + m_config = shader_config; + m_mem_config = mem_config; +} + +void power_stat_t::visualizer_print( gzFile visualizer_file ) +{ + pwr_core_stat->visualizer_print(visualizer_file); + pwr_mem_stat->visualizer_print(visualizer_file); +} + +void power_stat_t::print (FILE *fout) const +{ + fprintf(fout,"average_pipeline_duty_cycle=%f\n",*m_average_pipeline_duty_cycle); + pwr_core_stat->print(fout); + pwr_mem_stat->print(fout); +} + diff --git a/src/gpgpu-sim/power_stat.h b/src/gpgpu-sim/power_stat.h new file mode 100644 index 0000000..299bf43 --- /dev/null +++ b/src/gpgpu-sim/power_stat.h @@ -0,0 +1,613 @@ +// Copyright (c) 2009-2011, Tor M. Aamodt, Ahmed El-Shafiey, Tayler Hetherington +// The University of British Columbia +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// Neither the name of The University of British Columbia nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef POWER_STAT_H +#define POWER_STAT_H + +#include <stdio.h> +#include <zlib.h> +#include "mem_latency_stat.h" +#include "shader.h" +#include "gpu-sim.h" + +struct shader_core_power_stats_pod { + // [0] = Current stat, [1] = last reading + float *m_pipeline_duty_cycle[2]; + unsigned *m_num_decoded_insn[2]; // number of instructions committed by this shader core + unsigned *m_num_FPdecoded_insn[2]; // number of instructions committed by this shader core + unsigned *m_num_INTdecoded_insn[2]; // number of instructions committed by this shader core + unsigned *m_num_storequeued_insn[2]; + unsigned *m_num_loadqueued_insn[2]; + unsigned *m_num_ialu_acesses[2]; + unsigned *m_num_fp_acesses[2]; + unsigned *m_num_tex_inst[2]; + unsigned *m_num_imul_acesses[2]; + unsigned *m_num_imul32_acesses[2]; + unsigned *m_num_imul24_acesses[2]; + unsigned *m_num_fpmul_acesses[2]; + unsigned *m_num_idiv_acesses[2]; + unsigned *m_num_fpdiv_acesses[2]; + unsigned *m_num_sp_acesses[2]; + unsigned *m_num_sfu_acesses[2]; + unsigned *m_num_trans_acesses[2]; + unsigned *m_num_mem_acesses[2]; + unsigned *m_num_sp_committed[2]; + unsigned *m_num_sfu_committed[2]; + unsigned *m_num_mem_committed[2]; + unsigned *m_active_sp_lanes[2]; + unsigned *m_active_sfu_lanes[2]; + unsigned *m_read_regfile_acesses[2]; + unsigned *m_write_regfile_acesses[2]; + unsigned *m_non_rf_operands[2]; +}; + +class power_core_stat_t : public shader_core_power_stats_pod { +public: + power_core_stat_t(const struct shader_core_config *shader_config, shader_core_stats *core_stats); + void visualizer_print( gzFile visualizer_file ); + void print (FILE *fout); + void init(); + void save_stats(); + +private: + shader_core_stats * m_core_stats; + const shader_core_config *m_config; + float average_duty_cycle; + + +}; + +struct mem_power_stats_pod{ + // [0] = Current stat, [1] = last reading + unsigned *inst_c_read_access[2]; // Instruction cache read access + unsigned *inst_c_read_miss[2]; // Instruction cache read miss + unsigned *const_c_read_access[2]; // Constant cache read access + unsigned *const_c_read_miss[2]; // Constant cache read miss + unsigned *text_c_read_access[2]; // Texture cache read access + unsigned *text_c_read_miss[2]; // Texture cache read miss + unsigned *l1d_read_access[2]; // L1 Data cache read access + unsigned *l1d_read_miss[2]; // L1 Data cache read miss + unsigned *l1d_write_access[2]; // L1 Data cache write access + unsigned *l1d_write_miss[2]; // L1 Data cache write miss + unsigned *shmem_read_access[2]; // Shared memory access + + // Low level L2 stats + unsigned *n_l2_read_access[2]; + unsigned *n_l2_read_miss[2]; + unsigned *n_l2_write_access[2]; + unsigned *n_l2_write_miss[2]; + + // Low level DRAM stats + unsigned *n_cmd[2]; + unsigned *n_activity[2]; + unsigned *n_nop[2]; + unsigned *n_act[2]; + unsigned *n_pre[2]; + unsigned *n_rd[2]; + unsigned *n_wr[2]; + unsigned *n_req[2]; + + // Interconnect stats + unsigned *n_simt_to_mem[2]; + unsigned *n_mem_to_simt[2]; +}; + + + +class power_mem_stat_t : public mem_power_stats_pod{ +public: + power_mem_stat_t(const struct memory_config *mem_config, const struct shader_core_config *shdr_config, memory_stats_t *mem_stats, shader_core_stats *shdr_stats); + void visualizer_print( gzFile visualizer_file ); + void print (FILE *fout) const; + void init(); + void save_stats(); +private: + memory_stats_t *m_mem_stats; + shader_core_stats * m_core_stats; + const memory_config *m_config; + const shader_core_config *m_core_config; +}; + + +class power_stat_t { +public: + power_stat_t( const struct shader_core_config *shader_config,float * average_pipeline_duty_cycle,float * active_sms,shader_core_stats * shader_stats, const struct memory_config *mem_config,memory_stats_t * memory_stats); + void visualizer_print( gzFile visualizer_file ); + void print (FILE *fout) const; + void save_stats(){ + pwr_core_stat->save_stats(); + pwr_mem_stat->save_stats(); + *m_average_pipeline_duty_cycle=0; + *m_active_sms=0; + } + + unsigned get_total_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_decoded_insn[0][i]) - (pwr_core_stat->m_num_decoded_insn[1][i]); + } + return total_inst; + } + unsigned get_total_int_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_INTdecoded_insn[0][i]) - (pwr_core_stat->m_num_INTdecoded_insn[1][i]); + } + return total_inst; + } + unsigned get_total_fp_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_FPdecoded_insn[0][i]) - (pwr_core_stat->m_num_FPdecoded_insn[1][i]); + } + return total_inst; + } + unsigned get_total_load_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_loadqueued_insn[0][i]) - (pwr_core_stat->m_num_loadqueued_insn[1][i]); + } + return total_inst; + } + unsigned get_total_store_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_storequeued_insn[0][i]) - (pwr_core_stat->m_num_storequeued_insn[1][i]); + } + return total_inst; + } + unsigned get_sp_committed_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_sp_committed[0][i]) - (pwr_core_stat->m_num_sp_committed[1][i]); + } + return total_inst; + } + unsigned get_sfu_committed_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_sfu_committed[0][i]) - (pwr_core_stat->m_num_sfu_committed[1][i]); + } + return total_inst; + } + unsigned get_mem_committed_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_mem_committed[0][i]) - (pwr_core_stat->m_num_mem_committed[1][i]); + } + return total_inst; + } + unsigned get_committed_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_mem_committed[0][i]) - (pwr_core_stat->m_num_mem_committed[1][i]) + +(pwr_core_stat->m_num_sfu_committed[0][i]) - (pwr_core_stat->m_num_sfu_committed[1][i]) + +(pwr_core_stat->m_num_sp_committed[0][i]) - (pwr_core_stat->m_num_sp_committed[1][i]); + } + return total_inst; + } + unsigned get_regfile_reads(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_read_regfile_acesses[0][i]) - (pwr_core_stat->m_read_regfile_acesses[1][i]); + } + return total_inst; + } + unsigned get_regfile_writes(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_write_regfile_acesses[0][i]) - (pwr_core_stat->m_write_regfile_acesses[1][i]); + } + return total_inst; + } + + float get_pipeline_duty(){ + float total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_pipeline_duty_cycle[0][i]) - (pwr_core_stat->m_pipeline_duty_cycle[1][i]); + } + return total_inst; + } + + unsigned get_non_regfile_operands(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_non_rf_operands[0][i]) - (pwr_core_stat->m_non_rf_operands[1][i]); + } + return total_inst; + } + + unsigned get_sp_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_sp_acesses[0][i]) - (pwr_core_stat->m_num_sp_acesses[1][i]); + } + return total_inst; + } + + unsigned get_sfu_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_sfu_acesses[0][i]) - (pwr_core_stat->m_num_sfu_acesses[1][i]); + } + return total_inst; + } + unsigned get_trans_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_trans_acesses[0][i]) - (pwr_core_stat->m_num_trans_acesses[1][i]); + } + return total_inst; + } + + unsigned get_mem_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_mem_acesses[0][i]) - (pwr_core_stat->m_num_mem_acesses[1][i]); + } + return total_inst; + } + + unsigned get_intdiv_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_idiv_acesses[0][i]) - (pwr_core_stat->m_num_idiv_acesses[1][i]); + } + return total_inst; + } + + unsigned get_fpdiv_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_fpdiv_acesses[0][i]) - (pwr_core_stat->m_num_fpdiv_acesses[1][i]); + } + return total_inst; + } + + unsigned get_intmul32_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_imul32_acesses[0][i]) - (pwr_core_stat->m_num_imul32_acesses[1][i]); + } + return total_inst; + } + + unsigned get_intmul24_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_imul24_acesses[0][i]) - (pwr_core_stat->m_num_imul24_acesses[1][i]); + } + return total_inst; + } + + unsigned get_intmul_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_imul_acesses[0][i]) - (pwr_core_stat->m_num_imul_acesses[1][i])+ + (pwr_core_stat->m_num_imul24_acesses[0][i]) - (pwr_core_stat->m_num_imul24_acesses[1][i])+ + (pwr_core_stat->m_num_imul32_acesses[0][i]) - (pwr_core_stat->m_num_imul32_acesses[1][i]); + } + return total_inst; + } + + unsigned get_fpmul_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_fp_acesses[0][i]) - (pwr_core_stat->m_num_fp_acesses[1][i]); + } + return total_inst; + } + + float get_sp_active_lanes(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_active_sp_lanes[0][i]) - (pwr_core_stat->m_active_sp_lanes[1][i]); + } + return (total_inst/m_config->num_shader())/m_config->gpgpu_num_sp_units; + } + + float get_sfu_active_lanes(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_active_sfu_lanes[0][i]) - (pwr_core_stat->m_active_sfu_lanes[1][i]); } + + return (total_inst/m_config->num_shader())/m_config->gpgpu_num_sfu_units; + } + + unsigned get_tot_fpu_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_fp_acesses[0][i]) - (pwr_core_stat->m_num_fp_acesses[1][i])+ + (pwr_core_stat->m_num_fpdiv_acesses[0][i]) - (pwr_core_stat->m_num_fpdiv_acesses[1][i])+ + (pwr_core_stat->m_num_fpmul_acesses[0][i]) - (pwr_core_stat->m_num_fpmul_acesses[1][i])+ + (pwr_core_stat->m_num_imul24_acesses[0][i]) - (pwr_core_stat->m_num_imul24_acesses[1][i])+ + (pwr_core_stat->m_num_imul_acesses[0][i]) - (pwr_core_stat->m_num_imul_acesses[1][i]) ; + //printf("imul_accesses0: %d imul_acccesses1: %d imul0 - imul1: %d\n",(pwr_core_stat->m_num_imul_acesses[0][i]),(pwr_core_stat->m_num_imul_acesses[1][i]),(pwr_core_stat->m_num_imul_acesses[0][i]-pwr_core_stat->m_num_imul_acesses[1][i])); + //printf("imul24_accesses0: %d imul24_acccesses1: %d imu24l0 - imul241: %d\n",(pwr_core_stat->m_num_imul24_acesses[0][i]),(pwr_core_stat->m_num_imul24_acesses[1][i]),(pwr_core_stat->m_num_imul24_acesses[0][i]-pwr_core_stat->m_num_imul24_acesses[1][i])); + //printf("total_insn:%d\n",total_inst); + + + } + total_inst += get_total_load_inst()+get_total_store_inst()+get_tex_inst(); + return total_inst; + } + + unsigned get_tot_sfu_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+= + (pwr_core_stat->m_num_idiv_acesses[0][i]) - (pwr_core_stat->m_num_idiv_acesses[1][i])+ + (pwr_core_stat->m_num_imul32_acesses[0][i]) - (pwr_core_stat->m_num_imul32_acesses[1][i])+ + (pwr_core_stat->m_num_trans_acesses[0][i]) - (pwr_core_stat->m_num_trans_acesses[1][i]); + } + return total_inst; + } + + unsigned get_ialu_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_ialu_acesses[0][i]) - (pwr_core_stat->m_num_ialu_acesses[1][i]); + } + return total_inst; + } + + unsigned get_tex_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_tex_inst[0][i]) - (pwr_core_stat->m_num_tex_inst[1][i]); + } + return total_inst; + } + + unsigned get_constant_c_accesses(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_mem_stat->const_c_read_access[0][i]) - (pwr_mem_stat->const_c_read_access[1][i]); + } + return total_inst; + } + unsigned get_constant_c_misses(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_mem_stat->const_c_read_miss[0][i]) - (pwr_mem_stat->const_c_read_miss[1][i]); + } + return total_inst; + } + unsigned get_constant_c_hits(){ + return (get_constant_c_accesses()-get_constant_c_misses()); + } + unsigned get_texture_c_accesses(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_mem_stat->text_c_read_access[0][i]) - (pwr_mem_stat->text_c_read_access[1][i]); + } + return total_inst; + } + unsigned get_texture_c_misses(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_mem_stat->text_c_read_miss[0][i]) - (pwr_mem_stat->text_c_read_miss[1][i]); + } + return total_inst; + } + unsigned get_texture_c_hits(){ + return ( get_texture_c_accesses()- get_texture_c_misses()); + } + unsigned get_inst_c_accesses(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_mem_stat->inst_c_read_access[0][i]) - (pwr_mem_stat->inst_c_read_access[1][i]); + } + return total_inst; + } + unsigned get_inst_c_misses(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_mem_stat->inst_c_read_miss[0][i]) - (pwr_mem_stat->inst_c_read_miss[1][i]); + } + return total_inst; + } + unsigned get_inst_c_hits(){ + return (get_inst_c_accesses()-get_inst_c_misses()); + } + unsigned get_l1d_read_accesses(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_mem_stat->l1d_read_access[0][i]) - (pwr_mem_stat->l1d_read_access[1][i]); + } + return total_inst; + } + unsigned get_l1d_read_misses(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_mem_stat->l1d_read_miss[0][i]) - (pwr_mem_stat->l1d_read_miss[1][i]); + } + return total_inst; + } + unsigned get_l1d_read_hits(){ + return (get_l1d_read_accesses()-get_l1d_read_misses()); + } + unsigned get_l1d_write_accesses(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_mem_stat->l1d_write_access[0][i]) - (pwr_mem_stat->l1d_write_access[1][i]); + } + return total_inst; + } + unsigned get_l1d_write_misses(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_mem_stat->l1d_write_miss[0][i]) - (pwr_mem_stat->l1d_write_miss[1][i]); + } + return total_inst; + } + unsigned get_l1d_write_hits(){ + return (get_l1d_write_accesses()-get_l1d_write_misses()); + } + unsigned get_cache_misses(){ + return get_l1d_read_misses()+get_constant_c_misses()+get_l1d_write_misses()+ + get_texture_c_misses(); + } + + unsigned get_cache_read_misses(){ + return get_l1d_read_misses()+get_constant_c_misses()+ + get_texture_c_misses(); + } + + unsigned get_cache_write_misses(){ + return get_l1d_write_misses(); + } + + unsigned get_shmem_read_access(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_mem_stat->shmem_read_access[0][i]) - (pwr_mem_stat->shmem_read_access[1][i]); + } + return total_inst; + } + + unsigned get_l2_read_accesses(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_l2_read_access[0][i] - pwr_mem_stat->n_l2_read_access[1][i]); + } + return total; + } + + unsigned get_l2_read_misses(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_l2_read_miss[0][i] - pwr_mem_stat->n_l2_read_miss[1][i]); + } + return total; + } + + unsigned get_l2_read_hits(){ + return (get_l2_read_accesses()-get_l2_read_misses()); + } + + unsigned get_l2_write_accesses(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_l2_write_access[0][i] - pwr_mem_stat->n_l2_write_access[1][i]); + } + return total; + } + + unsigned get_l2_write_misses(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_l2_write_miss[0][i] - pwr_mem_stat->n_l2_write_miss[1][i]); + } + return total; + } + unsigned get_l2_write_hits(){ + return (get_l2_write_accesses()-get_l2_write_misses()); + } + unsigned get_dram_cmd(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_cmd[0][i] - pwr_mem_stat->n_cmd[1][i]); + } + return total; + } + unsigned get_dram_activity(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_activity[0][i] - pwr_mem_stat->n_activity[1][i]); + } + return total; + } + unsigned get_dram_nop(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_nop[0][i] - pwr_mem_stat->n_nop[1][i]); + } + return total; + } + unsigned get_dram_act(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_act[0][i] - pwr_mem_stat->n_act[1][i]); + } + return total; + } + unsigned get_dram_pre(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_pre[0][i] - pwr_mem_stat->n_pre[1][i]); + } + return total; + } + unsigned get_dram_rd(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_rd[0][i] - pwr_mem_stat->n_rd[1][i]); + } + return total; + } + unsigned get_dram_wr(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_wr[0][i] - pwr_mem_stat->n_wr[1][i]); + } + return total; + } + unsigned get_dram_req(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_req[0][i] - pwr_mem_stat->n_req[1][i]); + } + return total; + } + + unsigned get_icnt_simt_to_mem(){ + unsigned total=0; + for(unsigned i=0; i<m_config->num_shader(); ++i){ + total += (pwr_mem_stat->n_simt_to_mem[0][i] - pwr_mem_stat->n_simt_to_mem[1][i]); + } + return total; + } + + unsigned get_icnt_mem_to_simt(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_mem_to_simt[0][i] - pwr_mem_stat->n_mem_to_simt[1][i]); + } + return total; + } + + power_core_stat_t * pwr_core_stat; + power_mem_stat_t * pwr_mem_stat; + float * m_average_pipeline_duty_cycle; + float * m_active_sms; + const shader_core_config *m_config; + const struct memory_config *m_mem_config; +}; + + +#endif /*POWER_LATENCY_STAT_H*/ diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index fb8165f..4095cbc 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -209,13 +209,13 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, //m_fu = new simd_function_unit*[m_num_function_units]; for (int k = 0; k < m_config->gpgpu_num_sp_units; k++) { - m_fu.push_back(new sp_unit( &m_pipeline_reg[EX_WB], m_config )); + m_fu.push_back(new sp_unit( &m_pipeline_reg[EX_WB], m_config, this )); m_dispatch_port.push_back(ID_OC_SP); m_issue_port.push_back(OC_EX_SP); } for (int k = 0; k < m_config->gpgpu_num_sfu_units; k++) { - m_fu.push_back(new sfu( &m_pipeline_reg[EX_WB], m_config )); + m_fu.push_back(new sfu( &m_pipeline_reg[EX_WB], m_config, this )); m_dispatch_port.push_back(ID_OC_SFU); m_issue_port.push_back(OC_EX_SFU); } @@ -289,13 +289,63 @@ address_type shader_core_ctx::next_pc( int tid ) const return the_thread->get_pc(); // PC should already be updatd to next PC at this point (was set in shader_decode() last time thread ran) } +void gpgpu_sim::get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ) +{ + unsigned cluster_id = m_shader_config->sid_to_cluster(sid); + m_cluster[cluster_id]->get_pdom_stack_top_info(sid,tid,pc,rpc); +} + +void shader_core_ctx::get_pdom_stack_top_info( unsigned tid, unsigned *pc, unsigned *rpc ) const +{ + unsigned warp_id = tid/m_config->warp_size; + m_simt_stack[warp_id]->get_pdom_stack_top_info(pc,rpc); +} + void shader_core_stats::print( FILE* fout ) const { - unsigned icount_uarch=0; + unsigned long long thread_icount_uarch=0; + unsigned long long warp_icount_uarch=0; + unsigned l1_dcache_read_hits=0; + unsigned l1_dcache_read_misses=0; + unsigned l1_dcache_write_accesses=0; + unsigned l1_dcache_write_misses=0; + unsigned icache_hits=0; + unsigned icache_misses=0; + unsigned ccache_hits=0; + unsigned ccache_misses=0; + unsigned tcache_hits=0; + unsigned tcache_misses=0; + + + for(unsigned i=0; i < m_config->num_shader(); i++) { - icount_uarch += m_num_sim_insn[i]; + thread_icount_uarch += m_num_sim_insn[i]; + warp_icount_uarch += m_num_sim_winsn[i]; + l1_dcache_read_hits += l1d_read_access[i]-l1d_read_miss[i]; + l1_dcache_write_accesses += l1d_write_access[i]; + l1_dcache_read_misses += l1d_read_miss[i]; + l1_dcache_write_misses += l1d_write_miss[i]; + icache_hits+=inst_c_read_access[i]-inst_c_read_miss[i]; + icache_misses+=inst_c_read_miss[i]; + tcache_hits+=text_c_read_access[i]-text_c_read_miss[i]; + tcache_misses+=text_c_read_miss[i]; + ccache_hits+=const_c_read_access[i]-const_c_read_miss[i]; + ccache_misses+=const_c_read_miss[i]; } - fprintf(fout,"gpgpu_n_tot_icount = %u\n", icount_uarch); + fprintf(fout,"gpgpu_n_tot_thrd_icount = %lld\n", thread_icount_uarch); + fprintf(fout,"gpgpu_n_tot_w_icount = %lld\n", warp_icount_uarch); + fprintf(fout,"gpgpu_n_icache_hits = %d\n", icache_hits ); + fprintf(fout,"gpgpu_n_icache_misses = %d\n", icache_misses ); + fprintf(fout,"gpgpu_n_l1dcache_read_hits = %d\n", l1_dcache_read_hits ); + fprintf(fout,"gpgpu_n_l1dcache_read_misses = %d\n", l1_dcache_read_misses ); + fprintf(fout,"gpgpu_n_l1dcache_write_accesses = %d\n", l1_dcache_write_accesses ); + fprintf(fout,"gpgpu_n_l1dcache_wirte_misses = %d\n", l1_dcache_write_misses ); + fprintf(fout,"gpgpu_n_tcache_hits = %d\n", tcache_hits ); + fprintf(fout,"gpgpu_n_tcache_misses = %d\n", tcache_misses ); + fprintf(fout,"gpgpu_n_ccache_hits = %d\n", ccache_hits ); + fprintf(fout,"gpgpu_n_ccache_misses = %d\n", ccache_misses); + + fprintf(fout,"gpgpu_n_stall_shd_mem = %d\n", gpgpu_n_stall_shd_mem ); fprintf(fout,"gpgpu_n_mem_read_local = %d\n", gpgpu_n_mem_read_local); fprintf(fout,"gpgpu_n_mem_write_local = %d\n", gpgpu_n_mem_write_local); @@ -407,7 +457,7 @@ void shader_core_stats::visualizer_print( gzFile visualizer_file ) gzprintf(visualizer_file, "\n"); // warp instruction count per shader core gzprintf(visualizer_file, "shaderwarpinsncount: "); - for (unsigned i=0;i<m_config->num_shader();i++) + for (unsigned i=0;i<m_config->num_shader();i++) gzprintf(visualizer_file, "%u ", m_num_sim_winsn[i] ); gzprintf(visualizer_file, "\n"); // warp divergence per shader core @@ -429,10 +479,22 @@ void shader_core_ctx::decode() m_warp[m_inst_fetch_buffer.m_warp_id].ibuffer_fill(0,pI1); m_warp[m_inst_fetch_buffer.m_warp_id].inc_inst_in_pipeline(); if( pI1 ) { + m_stats->m_num_decoded_insn[m_sid]++; + if(pI1->op2==INT_OP){ + m_stats->m_num_INTdecoded_insn[m_sid]++; + }else if(pI1->op2==FP_OP) { + m_stats->m_num_FPdecoded_insn[m_sid]++; + } const warp_inst_t* pI2 = ptx_fetch_inst(pc+pI1->isize); if( pI2 ) { m_warp[m_inst_fetch_buffer.m_warp_id].ibuffer_fill(1,pI2); m_warp[m_inst_fetch_buffer.m_warp_id].inc_inst_in_pipeline(); + m_stats->m_num_decoded_insn[m_sid]++; + if(pI2->op2==INT_OP){ + m_stats->m_num_INTdecoded_insn[m_sid]++; + }else if(pI2->op2==FP_OP) { + m_stats->m_num_FPdecoded_insn[m_sid]++; + } } } m_inst_fetch_buffer.m_valid = false; @@ -508,6 +570,9 @@ void shader_core_ctx::fetch() m_L1I->cycle(); + // Power stats + m_L1I->get_stats(m_stats->inst_c_read_access[m_sid], m_stats->inst_c_read_miss[m_sid]); + assert(m_stats->inst_c_read_access[m_sid]>=m_stats->inst_c_read_miss[m_sid]); if( m_L1I->access_ready() ) { mem_fetch *mf = m_L1I->next_access(); m_warp[mf->get_wid()].clear_imiss_pending(); @@ -841,6 +906,7 @@ void shader_core_ctx::execute() unsigned multiplier = m_fu[n]->clock_multiplier(); for( unsigned c=0; c < multiplier; c++ ) m_fu[n]->cycle(); + m_fu[n]->active_lanes_in_pipeline(); enum pipeline_stage_name_t issue_port = m_issue_port[n]; register_set& issue_inst = m_pipeline_reg[ issue_port ]; warp_inst_t** ready_reg = issue_inst.get_ready(); @@ -866,20 +932,93 @@ void ldst_unit::print_cache_stats( FILE *fp, unsigned& dl1_accesses, unsigned& d } } -void shader_core_ctx::warp_inst_complete(const warp_inst_t &inst) +void ldst_unit::get_cache_stats(unsigned &read_accesses, unsigned &write_accesses, unsigned &read_misses, unsigned &write_misses, unsigned cache_type){ + switch(cache_type){ + default: + case 0: // L1D + if( m_L1D ) { + //m_L1D->get_stats(accesses, misses); + m_L1D->get_data_stats(read_accesses,read_misses,write_accesses, write_misses); + } + break; + case 1: + if( m_L1C ){ + m_L1C->get_stats(read_accesses, read_misses); + } + break; + case 2: + if( m_L1T ){ + m_L1T->get_stats(read_accesses, read_misses); + } + } +} + +void ldst_unit::set_stats(){ + // Sets the cache stats in m_stats + if( m_L1D ) { + m_L1D->get_data_stats(m_stats->l1d_read_access[m_sid], m_stats->l1d_read_miss[m_sid],m_stats->l1d_write_access[m_sid], m_stats->l1d_write_miss[m_sid]); + } + if( m_L1C ){ + m_L1C->get_stats(m_stats->const_c_read_access[m_sid], m_stats->const_c_read_miss[m_sid]); + } + if( m_L1T ){ + m_L1T->get_stats(m_stats->text_c_read_access[m_sid], m_stats->text_c_read_miss[m_sid]); + } +} + +void ldst_unit::set_icnt_power_stats(unsigned &simt_to_mem) const{ + unsigned l1d=0; + unsigned tex=0; + unsigned l1c=0; + + m_L1D->set_icnt_power_stats(l1d); + m_L1T->set_icnt_power_stats(tex); + m_L1C->set_icnt_power_stats(l1c); + + simt_to_mem = n_simt_to_mem+l1d+tex+l1c; // All components that push packets into the interconnect +} + +void shader_core_ctx::warp_inst_complete(const warp_inst_t &inst, bool memory) { #if 0 printf("[warp_inst_complete] uid=%u core=%u warp=%u pc=%#x @ time=%llu issued@%llu\n", inst.get_uid(), m_sid, inst.warp_id(), inst.pc, gpu_tot_sim_cycle + gpu_sim_cycle, inst.get_issue_cycle()); #endif - m_stats->m_num_sim_insn[m_sid] += inst.issued_count(); - m_stats->m_num_sim_winsn[m_sid]++; - m_gpu->gpu_sim_insn += inst.issued_count(); - inst.completed(gpu_tot_sim_cycle + gpu_sim_cycle); + if(inst.op4==SP__OP) + m_stats->m_num_sp_committed[m_sid]++; + else if(inst.op4==SFU__OP) + m_stats->m_num_sfu_committed[m_sid]++; + else if(inst.op4==MEM__OP) + m_stats->m_num_mem_committed[m_sid]++; + + if(memory==0){ + m_stats->m_num_sim_insn[m_sid] += inst.active_count(); + m_stats->m_num_sim_winsn[m_sid]++; + } + m_gpu->gpu_sim_insn += inst.active_count(); + inst.completed(gpu_tot_sim_cycle + gpu_sim_cycle); } void shader_core_ctx::writeback() { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_pipeline_duty_cycle[m_sid]=roundUp((m_stats->m_num_sim_insn[m_sid]-m_stats->m_last_num_sim_insn[m_sid])/(64.0)); + } else { + m_stats->m_pipeline_duty_cycle[m_sid]=(m_stats->m_num_sim_insn[m_sid]-m_stats->m_last_num_sim_insn[m_sid])/(64.0); + } + + //assert(m_stats->m_pipeline_duty_cycle[m_sid]<=4*32); + if((m_stats->m_num_sim_winsn[m_sid]-m_stats->m_last_num_sim_winsn[m_sid])<5){ + m_stats->inst_per_cycle[(m_stats->m_num_sim_winsn[m_sid]-m_stats->m_last_num_sim_winsn[m_sid])][m_sid]++; + } + else{ + m_stats->inst_per_cycle[5][m_sid]++; + } + + + m_stats->m_last_num_sim_insn[m_sid]=m_stats->m_num_sim_insn[m_sid]; + m_stats->m_last_num_sim_winsn[m_sid]=m_stats->m_num_sim_winsn[m_sid]; + warp_inst_t** preg = m_pipeline_reg[EX_WB].get_ready(); warp_inst_t* pipe_reg = (preg==NULL)? NULL:*preg; while( preg and !pipe_reg->empty() ) { @@ -903,7 +1042,7 @@ void shader_core_ctx::writeback() unsigned warp_id = pipe_reg->warp_id(); m_scoreboard->releaseRegisters( pipe_reg ); m_warp[warp_id].dec_inst_in_pipeline(); - warp_inst_complete(*pipe_reg); + warp_inst_complete(*pipe_reg,0); m_gpu->gpu_sim_insn_last_update_sid = m_sid; m_gpu->gpu_sim_insn_last_update = gpu_sim_cycle; m_last_inst_gpu_sim_cycle = gpu_sim_cycle; @@ -918,6 +1057,11 @@ bool ldst_unit::shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, { if( inst.space.get_type() != shared_space ) return true; + + if(inst.has_dispatch_delay()){ + m_stats->gpgpu_n_shmem_bank_access[m_sid]++; + } + bool stall = inst.dispatch_delay(); if( stall ) { fail_type = S_MEM; @@ -1019,6 +1163,7 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea } else { mem_fetch *mf = m_mf_allocator->alloc(inst,access); m_icnt->push(mf); + n_simt_to_mem+=mf->get_num_flits(true); // Interconnect power stats (# of flits sent to the memory partitions) inst.accessq_pop_back(); //inst.clear_active( access.get_warp_mask() ); if( inst.is_load() ) { @@ -1057,9 +1202,9 @@ void ldst_unit::fill( mem_fetch *mf ) m_response_fifo.push_back(mf); } -void ldst_unit::flush() -{ - // no L1D +void ldst_unit::flush(){ + // Flush L1D cache + m_L1D->flush(); } simd_function_unit::simd_function_unit( const shader_core_config *config ) @@ -1068,20 +1213,61 @@ simd_function_unit::simd_function_unit( const shader_core_config *config ) m_dispatch_reg = new warp_inst_t(config); } -sfu::sfu( register_set* result_port, const shader_core_config *config ) - : pipelined_simd_unit(result_port,config,config->max_sfu_latency) + +sfu:: sfu( register_set* result_port, const shader_core_config *config,shader_core_ctx *core ) + : pipelined_simd_unit(result_port,config,config->max_sfu_latency,core) { m_name = "SFU"; } -sp_unit::sp_unit( register_set* result_port, const shader_core_config *config ) - : pipelined_simd_unit(result_port,config,config->max_sp_latency) +void sfu::issue( register_set& source_reg ) +{ + warp_inst_t** ready_reg = source_reg.get_ready(); + //m_core->incexecstat((*ready_reg)); + + (*ready_reg)->op4=SFU__OP; + m_core->incsfu_stat(m_core->get_sid(),m_core->get_config()->warp_size,(*ready_reg)->latency); + pipelined_simd_unit::issue(source_reg); +} + +void ldst_unit::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incfumemactivelanes_stat(m_core->get_sid(),active_count); +} +void sp_unit::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incspactivelanes_stat(m_core->get_sid(),active_count); + m_core->incfuactivelanes_stat(m_core->get_sid(),active_count); + m_core->incfumemactivelanes_stat(m_core->get_sid(),active_count); +} + +void sfu::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incsfuactivelanes_stat(m_core->get_sid(),active_count); + m_core->incfuactivelanes_stat(m_core->get_sid(),active_count); + m_core->incfumemactivelanes_stat(m_core->get_sid(),active_count); +} + +sp_unit::sp_unit( register_set* result_port, const shader_core_config *config,shader_core_ctx *core) + : pipelined_simd_unit(result_port,config,config->max_sp_latency,core) { m_name = "SP "; } +void sp_unit :: issue(register_set& source_reg) +{ + warp_inst_t** ready_reg = source_reg.get_ready(); + //m_core->incexecstat((*ready_reg)); + (*ready_reg)->op4=SP__OP; + m_core->incsp_stat(m_core->get_sid(),m_core->get_config()->warp_size,(*ready_reg)->latency); + pipelined_simd_unit::issue(source_reg); +} + -pipelined_simd_unit::pipelined_simd_unit( register_set* result_port, const shader_core_config *config, unsigned max_latency ) +pipelined_simd_unit::pipelined_simd_unit( register_set* result_port, const shader_core_config *config, unsigned max_latency,shader_core_ctx *core ) : simd_function_unit(config) { m_result_port = result_port; @@ -1089,8 +1275,29 @@ pipelined_simd_unit::pipelined_simd_unit( register_set* result_port, const shade m_pipeline_reg = new warp_inst_t*[m_pipeline_depth]; for( unsigned i=0; i < m_pipeline_depth; i++ ) m_pipeline_reg[i] = new warp_inst_t( config ); + m_core=core; +} + + +void pipelined_simd_unit::issue( register_set& source_reg ) +{ + //move_warp(m_dispatch_reg,source_reg); + warp_inst_t** ready_reg = source_reg.get_ready(); + m_core->incexecstat((*ready_reg)); + //source_reg.move_out_to(m_dispatch_reg); + simd_function_unit::issue(source_reg); } +/* + virtual void issue( register_set& source_reg ) + { + //move_warp(m_dispatch_reg,source_reg); + //source_reg.move_out_to(m_dispatch_reg); + simd_function_unit::issue(source_reg); + } +*/ + + ldst_unit::ldst_unit( mem_fetch_interface *icnt, shader_core_mem_fetch_allocator *mf_allocator, shader_core_ctx *core, @@ -1098,9 +1305,9 @@ ldst_unit::ldst_unit( mem_fetch_interface *icnt, Scoreboard *scoreboard, const shader_core_config *config, const memory_config *mem_config, - shader_core_stats *stats, + shader_core_stats *stats, unsigned sid, - unsigned tpc ) : pipelined_simd_unit(NULL,config,3), m_next_wb(config) + unsigned tpc ) : pipelined_simd_unit(NULL,config,3,core), m_next_wb(config) { m_memory_config = mem_config; m_icnt = icnt; @@ -1131,6 +1338,32 @@ ldst_unit::ldst_unit( mem_fetch_interface *icnt, m_last_inst_gpu_tot_sim_cycle=0; } +void ldst_unit:: issue( register_set ®_set ) +{ + warp_inst_t* inst = *(reg_set.get_ready()); + // stat collection + m_core->mem_instruction_stats(*inst); + + // record how many pending register writes/memory accesses there are for this instruction + assert(inst->empty() == false); + if (inst->is_load() and inst->space.get_type() != shared_space) { + unsigned warp_id = inst->warp_id(); + unsigned n_accesses = inst->accessq_count(); + for (unsigned r = 0; r < 4; r++) { + unsigned reg_id = inst->out[r]; + if (reg_id > 0) { + m_pending_writes[warp_id][reg_id] += n_accesses; + } + } + } + + + inst->op4=MEM__OP; + m_core->mem_instruction_stats(*inst); + m_core->incmem_stat(m_core->get_sid(),m_core->get_config()->warp_size,1); + pipelined_simd_unit::issue(reg_set); +} + void ldst_unit::writeback() { // process next instruction that is going to writeback @@ -1154,7 +1387,7 @@ void ldst_unit::writeback() } } if( insn_completed ) { - m_core->warp_inst_complete(m_next_wb); + m_core->warp_inst_complete(m_next_wb, 1); } m_next_wb.clear(); m_last_inst_gpu_sim_cycle = gpu_sim_cycle; @@ -1227,7 +1460,7 @@ unsigned ldst_unit::clock_multiplier() const { return m_config->mem_warp_parts; } - +/* void ldst_unit::issue( register_set ®_set ) { warp_inst_t* inst = *(reg_set.get_ready()); @@ -1249,7 +1482,7 @@ void ldst_unit::issue( register_set ®_set ) pipelined_simd_unit::issue(reg_set); } - +*/ void ldst_unit::cycle() { writeback(); @@ -1337,7 +1570,7 @@ void ldst_unit::cycle() } } if( !pending_requests ) { - m_core->warp_inst_complete(*m_dispatch_reg); + m_core->warp_inst_complete(*m_dispatch_reg, 1); m_scoreboard->releaseRegisters(m_dispatch_reg); } m_core->dec_inst_in_pipeline(warp_id); @@ -1346,10 +1579,13 @@ void ldst_unit::cycle() } else { // stores exit pipeline here m_core->dec_inst_in_pipeline(warp_id); - m_core->warp_inst_complete(*m_dispatch_reg); + m_core->get_gpu()->gpu_sim_insn += m_dispatch_reg->active_count(); + m_core->warp_inst_complete(*m_dispatch_reg,1); m_dispatch_reg->clear(); } } + // Sets stats in m_stats object + set_stats(); } void shader_core_ctx::register_cta_thread_exit( unsigned cta_num ) @@ -1481,7 +1717,81 @@ void warp_inst_t::print( FILE *fout ) const ptx_print_insn( pc, fout ); fprintf(fout, "\n"); } +void shader_core_ctx::incexecstat(warp_inst_t *&inst) +{ + if(inst->op5==TEX) + inctex_stat(get_sid(),inst->active_count(),1); + + switch(inst->op3){ + case INT__OP: + incialu_stat(get_sid(),inst->active_count(),25); + break; + case INT_MUL_OP: + if(m_config->gpgpu_shader_registers==32768) //i.e. FERMI + incimul_stat(get_sid(),inst->active_count(),7.2); + else + incimul_stat(get_sid(),inst->active_count(),16); + break; + case INT_MUL24_OP: + incimul24_stat(get_sid(),inst->active_count(),4.2); + break; + case INT_MUL32_OP: + incimul32_stat(get_sid(),inst->active_count(),4); + break; + case INT_DIV_OP: + incidiv_stat(get_sid(),inst->active_count(),40); + break; + case FP__OP: + if(m_config->gpgpu_shader_registers==32768) + incfpalu_stat(get_sid(),inst->active_count(),1); + else + incfpalu_stat(get_sid(),inst->active_count(),1.7); + break; + case FP_MUL_OP: + if(m_config->gpgpu_shader_registers==32768) + incfpmul_stat(get_sid(),inst->active_count(),1.8); + else + incfpmul_stat(get_sid(),inst->active_count(),1.8); + break; + case FP_DIV_OP: + if(m_config->gpgpu_shader_registers==32768) + incfpdiv_stat(get_sid(),inst->active_count(),48); + else + incfpdiv_stat(get_sid(),inst->active_count(),22); + break; + case FP_SQRT_OP: + if(m_config->gpgpu_shader_registers==32768) + inctrans_stat(get_sid(),inst->active_count(),25); + else + inctrans_stat(get_sid(),inst->active_count(),8); + + break; + case FP_LG_OP: + if (m_config->gpgpu_shader_registers==32768) + inctrans_stat(get_sid(),inst->active_count(),35); + else + inctrans_stat(get_sid(),inst->active_count(),0.3); + break; + case FP_SIN_OP: + if(m_config->gpgpu_shader_registers==32768) + inctrans_stat(get_sid(),inst->active_count(),12); + else + inctrans_stat(get_sid(),inst->active_count(),40); + + break; + case FP_EXP_OP: + if(m_config->gpgpu_shader_registers==32768) + inctrans_stat(get_sid(),inst->active_count(),35); + else + inctrans_stat(get_sid(),inst->active_count(),9); + break; + + + default: + break; + } +} void shader_core_ctx::print_stage(unsigned int stage, FILE *fout ) const { m_pipeline_reg[stage].print(fout); @@ -1710,6 +2020,7 @@ unsigned int shader_core_config::max_cta( const kernel_info_t &k ) const void shader_core_ctx::cycle() { + m_stats->shader_cycles[m_sid]++; writeback(); execute(); read_operands(); @@ -2010,6 +2321,19 @@ void shader_core_ctx::print_cache_stats( FILE *fp, unsigned& dl1_accesses, unsig m_ldst_unit->print_cache_stats( fp, dl1_accesses, dl1_misses ); } +void shader_core_ctx::get_cache_stats(unsigned &read_accesses, unsigned &write_accesses, unsigned &read_misses, unsigned &write_misses, unsigned cache_type) { + m_ldst_unit->get_cache_stats(read_accesses, write_accesses, read_misses, write_misses, cache_type); +} + +void shader_core_ctx::set_icnt_power_stats(unsigned &n_simt_to_mem) const{ + unsigned l1i=0; + + m_L1I->set_icnt_power_stats(l1i); + m_ldst_unit->set_icnt_power_stats(n_simt_to_mem); + + n_simt_to_mem+=l1i; // l1i + l1d + l1c + l1t + any non-cached access +} + bool shd_warp_t::functional_done() const { return get_n_completed() == m_warp_size; @@ -2151,6 +2475,22 @@ bool opndcoll_rfu_t::writeback( const warp_inst_t &inst ) return false; } } + for(unsigned i=0;i<(unsigned)regs.size();i++){ + if(m_shader->get_config()->gpgpu_clock_gated_reg_file){ + unsigned active_count=0; + for(unsigned i=0;i<m_shader->get_config()->warp_size;i=i+m_shader->get_config()->n_regfile_gating_group){ + for(unsigned j=0;j<m_shader->get_config()->n_regfile_gating_group;j++){ + if(inst.get_active_mask().test(i+j)){ + active_count+=m_shader->get_config()->n_regfile_gating_group; + break; + } + } + } + m_shader->incregfile_writes(m_shader->get_sid(),active_count); + }else{ + m_shader->incregfile_writes(m_shader->get_sid(),m_shader->get_config()->warp_size);//inst.active_count()); + } + } return true; } @@ -2160,6 +2500,22 @@ void opndcoll_rfu_t::dispatch_ready_cu() dispatch_unit_t &du = m_dispatch_units[p]; collector_unit_t *cu = du.find_ready(); if( cu ) { + for(unsigned i=0;i<(cu->get_num_operands()-cu->get_num_regs());i++){ + if(m_shader->get_config()->gpgpu_clock_gated_reg_file){ + unsigned active_count=0; + for(unsigned i=0;i<m_shader->get_config()->warp_size;i=i+m_shader->get_config()->n_regfile_gating_group){ + for(unsigned j=0;j<m_shader->get_config()->n_regfile_gating_group;j++){ + if(cu->get_active_mask().test(i+j)){ + active_count+=m_shader->get_config()->n_regfile_gating_group; + break; + } + } + } + m_shader->incnon_rf_operands(m_shader->get_sid(),active_count); + }else{ + m_shader->incnon_rf_operands(m_shader->get_sid(),m_shader->get_config()->warp_size);//cu->get_active_count()); + } + } cu->dispatch(); } } @@ -2208,7 +2564,21 @@ void opndcoll_rfu_t::allocate_reads() unsigned cu = op.get_oc_id(); unsigned operand = op.get_operand(); m_cu[cu]->collect_operand(operand); - } + if(m_shader->get_config()->gpgpu_clock_gated_reg_file){ + unsigned active_count=0; + for(unsigned i=0;i<m_shader->get_config()->warp_size;i=i+m_shader->get_config()->n_regfile_gating_group){ + for(unsigned j=0;j<m_shader->get_config()->n_regfile_gating_group;j++){ + if(op.get_active_mask().test(i+j)){ + active_count+=m_shader->get_config()->n_regfile_gating_group; + break; + } + } + } + m_shader->incregfile_reads(m_shader->get_sid(),active_count); + }else{ + m_shader->incregfile_reads(m_shader->get_sid(),m_shader->get_config()->warp_size);//op.get_active_count()); + } + } } bool opndcoll_rfu_t::collector_unit_t::ready() const @@ -2348,6 +2718,14 @@ unsigned simt_core_cluster::get_n_active_cta() const return n; } +unsigned simt_core_cluster::get_n_active_sms() const +{ + unsigned n=0; + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + n += m_core[i]->isactive(); + return n; +} + unsigned simt_core_cluster::issue_block2core() { unsigned num_blocks_issued=0; @@ -2443,6 +2821,12 @@ void simt_core_cluster::icnt_cycle() } } +void simt_core_cluster::get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ) const +{ + unsigned cid = m_config->sid_to_cid(sid); + m_core[cid]->get_pdom_stack_top_info(tid,pc,rpc); +} + void simt_core_cluster::display_pipeline( unsigned sid, FILE *fout, int print_mem, int mask ) { m_core[m_config->sid_to_cid(sid)]->display_pipeline(fout,print_mem,mask); @@ -2462,6 +2846,18 @@ void simt_core_cluster::print_cache_stats( FILE *fp, unsigned& dl1_accesses, uns } } +void simt_core_cluster::get_cache_stats(unsigned &read_accesses, unsigned &write_accesses, unsigned &read_misses, unsigned &write_misses, unsigned cache_type) const { + for ( unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i ) { + m_core[ i ]->get_cache_stats(read_accesses, write_accesses, read_misses, write_misses, cache_type); + } +} + +void simt_core_cluster::set_icnt_stats(unsigned &n_simt_to_mem) const { + for ( unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i ) { + m_core[i]->set_icnt_power_stats(n_simt_to_mem); + } +} + void shader_core_ctx::checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t, unsigned tid) { if( inst.has_callback(t) ) diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 262a3be..047f4da 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -53,6 +53,8 @@ #include "stats.h" #include "gpu-cache.h" + + #define NO_OP_FLAG 0xFF /* READ_PACKET_SIZE: @@ -413,7 +415,24 @@ private: if( m_warp ) return m_warp->warp_id(); else if( m_cu ) return m_cu->get_warp_id(); else abort(); - return 0; + } + unsigned get_active_count() const + { + if( m_warp ) return m_warp->active_count(); + else if( m_cu ) return m_cu->get_active_count(); + else abort(); + } + const active_mask_t & get_active_mask() + { + if( m_warp ) return m_warp->get_active_mask(); + else if( m_cu ) return m_cu->get_active_mask(); + else abort(); + } + unsigned get_op3() const + { + if( m_warp ) return m_warp->op3; + else if( m_cu ) return m_cu->get_op3(); + else abort(); } unsigned get_oc_id() const { return m_cu->get_id(); } unsigned get_bank() const { return m_bank; } @@ -605,6 +624,9 @@ private: void dump(FILE *fp, const shader_core_ctx *shader ) const; unsigned get_warp_id() const { return m_warp_id; } + unsigned get_active_count() const { return m_warp->active_count(); } + const active_mask_t & get_active_mask() const { return m_warp->get_active_mask(); } + unsigned get_op3() const { return m_warp->op3; } unsigned get_id() const { return m_cuid; } // returns CU hw id // modifiers @@ -619,7 +641,12 @@ private: { m_not_ready.reset(op); } - + unsigned get_num_operands() const{ + return m_warp->get_num_operands(); + } + unsigned get_num_regs() const{ + return m_warp->get_num_regs(); + } void dispatch(); bool is_free(){return m_free;} @@ -762,6 +789,7 @@ public: // modifiers virtual void issue( register_set& source_reg ) { source_reg.move_out_to(m_dispatch_reg); occupied.set(m_dispatch_reg->latency);} virtual void cycle() = 0; + virtual void active_lanes_in_pipeline() = 0; // accessors virtual unsigned clock_multiplier() const { return 1; } @@ -782,7 +810,7 @@ protected: class pipelined_simd_unit : public simd_function_unit { public: - pipelined_simd_unit( register_set* result_port, const shader_core_config *config, unsigned max_latency ); + pipelined_simd_unit( register_set* result_port, const shader_core_config *config, unsigned max_latency, shader_core_ctx *core ); //modifiers virtual void cycle() @@ -800,14 +828,26 @@ public: } occupied >>=1; } - + virtual void issue( register_set& source_reg ); + virtual unsigned get_active_lanes_in_pipeline() + { + active_mask_t active_lanes; + active_lanes.reset(); + for( unsigned stage=0; (stage+1)<m_pipeline_depth; stage++ ){ + if( !m_pipeline_reg[stage]->empty() ) + active_lanes|=m_pipeline_reg[stage]->get_active_mask(); + } + return active_lanes.count(); + } + virtual void active_lanes_in_pipeline() = 0; +/* virtual void issue( register_set& source_reg ) { //move_warp(m_dispatch_reg,source_reg); //source_reg.move_out_to(m_dispatch_reg); simd_function_unit::issue(source_reg); } - +*/ // accessors virtual bool stallable() const { return false; } virtual bool can_issue( const warp_inst_t &inst ) const @@ -828,12 +868,13 @@ protected: unsigned m_pipeline_depth; warp_inst_t **m_pipeline_reg; register_set *m_result_port; + class shader_core_ctx *m_core; }; class sfu : public pipelined_simd_unit { public: - sfu( register_set* result_port, const shader_core_config *config ); + sfu( register_set* result_port, const shader_core_config *config, shader_core_ctx *core ); virtual bool can_issue( const warp_inst_t &inst ) const { switch(inst.op) { @@ -843,12 +884,14 @@ public: } return pipelined_simd_unit::can_issue(inst); } + virtual void active_lanes_in_pipeline(); + virtual void issue( register_set& source_reg ); }; class sp_unit : public pipelined_simd_unit { public: - sp_unit( register_set* result_port, const shader_core_config *config ); + sp_unit( register_set* result_port, const shader_core_config *config, shader_core_ctx *core ); virtual bool can_issue( const warp_inst_t &inst ) const { switch(inst.op) { @@ -860,6 +903,8 @@ public: } return pipelined_simd_unit::can_issue(inst); } + virtual void active_lanes_in_pipeline(); + virtual void issue( register_set& source_reg ); }; class simt_core_cluster; @@ -900,10 +945,16 @@ public: } return m_dispatch_reg->empty(); } + + virtual void active_lanes_in_pipeline(); virtual bool stallable() const { return true; } bool response_buffer_full() const; void print(FILE *fout) const; void print_cache_stats( FILE *fp, unsigned& dl1_accesses, unsigned& dl1_misses ); + void get_cache_stats(unsigned &read_accesses, unsigned &write_accesses, unsigned &read_misses, unsigned &write_misses, unsigned cache_type); + void set_stats(); + + void set_icnt_power_stats(unsigned &simt_to_mem) const; private: bool shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type); @@ -940,6 +991,9 @@ private: // for debugging unsigned long long m_last_inst_gpu_sim_cycle; unsigned long long m_last_inst_gpu_tot_sim_cycle; + + // Interconnect power stats + unsigned n_simt_to_mem; }; enum pipeline_stage_name_t { @@ -969,6 +1023,7 @@ struct shader_core_config : public core_config shader_core_config(){ pipeline_widths_string = NULL; } + void init() { int ntok = sscanf(gpgpu_shader_core_pipeline_opt,"%d:%d", @@ -1019,8 +1074,11 @@ struct shader_core_config : public core_config // data char *gpgpu_shader_core_pipeline_opt; bool gpgpu_perfect_mem; + bool gpgpu_clock_gated_reg_file; + bool gpgpu_clock_gated_lanes; enum divergence_support_t model; unsigned n_thread_per_shader; + unsigned n_regfile_gating_group; unsigned max_warps_per_shader; unsigned max_cta_per_core; //Limit on number of concurrent CTAs in shader core @@ -1033,7 +1091,8 @@ struct shader_core_config : public core_config cache_config m_L1T_config; cache_config m_L1C_config; cache_config m_L1D_config; - + cache_config m_L2D_config; + bool gpgpu_dwf_reg_bankconflict; int gpgpu_num_sched_per_core; @@ -1080,8 +1139,44 @@ struct shader_core_config : public core_config }; struct shader_core_stats_pod { + + unsigned long long **inst_per_cycle; + unsigned long long *shader_cycles; unsigned *m_num_sim_insn; // number of scalar thread instructions committed by this shader core unsigned *m_num_sim_winsn; // number of warp instructions committed by this shader core + unsigned *m_last_num_sim_insn; + unsigned *m_last_num_sim_winsn; + unsigned *m_num_decoded_insn; // number of instructions decoded by this shader core + float *m_pipeline_duty_cycle; + unsigned *m_num_FPdecoded_insn; + unsigned *m_num_INTdecoded_insn; + unsigned *m_num_storequeued_insn; + unsigned *m_num_loadqueued_insn; + unsigned *m_num_ialu_acesses; + unsigned *m_num_fp_acesses; + unsigned *m_num_imul_acesses; + unsigned *m_num_tex_inst; + unsigned *m_num_fpmul_acesses; + unsigned *m_num_idiv_acesses; + unsigned *m_num_fpdiv_acesses; + unsigned *m_num_sp_acesses; + unsigned *m_num_sfu_acesses; + unsigned *m_num_trans_acesses; + unsigned *m_num_mem_acesses; + unsigned *m_num_sp_committed; + unsigned *m_num_tlb_hits; + unsigned *m_num_tlb_accesses; + unsigned *m_num_sfu_committed; + unsigned *m_num_mem_committed; + unsigned *m_read_regfile_acesses; + unsigned *m_write_regfile_acesses; + unsigned *m_non_rf_operands; + unsigned *m_num_imul24_acesses; + unsigned *m_num_imul32_acesses; + unsigned *m_active_sp_lanes; + unsigned *m_active_sfu_lanes; + unsigned *m_active_fu_lanes; + unsigned *m_active_fu_mem_lanes; unsigned *m_n_diverge; // number of divergence occurring in this shader unsigned gpgpu_n_load_insn; unsigned gpgpu_n_store_insn; @@ -1114,9 +1209,23 @@ struct shader_core_stats_pod { unsigned made_write_mfs; unsigned made_read_mfs; + + // Power stats + unsigned *gpgpu_n_shmem_bank_access; + unsigned *inst_c_read_access; // Instruction cache read access + unsigned *inst_c_read_miss; // Instruction cache read miss + unsigned *const_c_read_access; // Constant cache read access + unsigned *const_c_read_miss; // Constant cache read miss + unsigned *text_c_read_access; // Texture cache read access + unsigned *text_c_read_miss; // Texture cache read miss + unsigned *l1d_read_access; // L1 Data cache read access + unsigned *l1d_read_miss; // L1 Data cache read miss + unsigned *l1d_write_access; // L1 Data cache write access + unsigned *l1d_write_miss; // L1 Data cache write miss + }; -class shader_core_stats : private shader_core_stats_pod { +class shader_core_stats : public shader_core_stats_pod { public: shader_core_stats( const shader_core_config *config ) { @@ -1124,11 +1233,64 @@ public: shader_core_stats_pod *pod = this; memset(pod,0,sizeof(shader_core_stats_pod)); + inst_per_cycle=(unsigned long long **) calloc(6,sizeof(unsigned long long *)); + for(unsigned i=0;i<6;i++){ + inst_per_cycle[i]=(unsigned long long *) calloc(config->num_shader(),sizeof(unsigned long long )); + } + shader_cycles=(unsigned long long *) calloc(config->num_shader(),sizeof(unsigned long long )); m_num_sim_insn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_sim_winsn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_last_num_sim_winsn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_last_num_sim_insn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_pipeline_duty_cycle=(float*) calloc(config->num_shader(),sizeof(float)); + m_num_decoded_insn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_FPdecoded_insn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_storequeued_insn=(unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_loadqueued_insn=(unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_INTdecoded_insn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_ialu_acesses = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_fp_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_tex_inst= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_imul_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_imul24_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_imul32_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_fpmul_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_idiv_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_fpdiv_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_sp_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_sfu_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_trans_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_mem_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_sp_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_tlb_hits=(unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_tlb_accesses=(unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_active_sp_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_active_sfu_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_active_fu_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_active_fu_mem_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_sfu_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_mem_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_read_regfile_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_write_regfile_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_non_rf_operands=(unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_n_diverge = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); shader_cycle_distro = (unsigned*) calloc(config->warp_size+3, sizeof(unsigned)); last_shader_cycle_distro = (unsigned*) calloc(m_config->warp_size+3, sizeof(unsigned)); + + // Power stats + inst_c_read_access = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + inst_c_read_miss = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + const_c_read_access = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + const_c_read_miss = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + text_c_read_access = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + text_c_read_miss = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + l1d_read_access = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + l1d_read_miss = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + l1d_write_access = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + l1d_write_miss = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + + gpgpu_n_shmem_bank_access = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + } void new_grid() { @@ -1141,6 +1303,7 @@ public: private: const shader_core_config *m_config; + friend class power_stat_t; friend class shader_core_ctx; friend class ldst_unit; friend class simt_core_cluster; @@ -1216,13 +1379,20 @@ public: printf("GPGPU-Sim uArch: Shader %d bind to kernel %u \'%s\'\n", m_sid, m_kernel->get_uid(), m_kernel->name().c_str() ); } - + + float roundUp(float num){ + return (int)num+((num-(int)(num)>0)?0.5:0.0); + } + + // accessors bool fetch_unit_response_buffer_full() const; bool ldst_unit_response_buffer_full() const; unsigned get_not_completed() const { return m_not_completed; } unsigned get_n_active_cta() const { return m_n_active_cta; } + unsigned isactive() const {if(m_n_active_cta>0) return 1; else return 0;} kernel_info_t *get_kernel() { return m_kernel; } + unsigned get_sid() const {return m_sid;} // used by functional simulation: // modifiers @@ -1230,6 +1400,7 @@ public: // accessors virtual bool warp_waiting_at_barrier( unsigned warp_id ) const; + void get_pdom_stack_top_info( unsigned tid, unsigned *pc, unsigned *rpc ) const; // used by pipeline timing model components: // modifiers @@ -1240,18 +1411,128 @@ public: void store_ack( class mem_fetch *mf ); bool warp_waiting_at_mem_barrier( unsigned warp_id ); void set_max_cta( const kernel_info_t &kernel ); - void warp_inst_complete(const warp_inst_t &inst); + void warp_inst_complete(const warp_inst_t &inst,bool memory); // accessors std::list<unsigned> get_regs_written( const inst_t &fvt ) const; const shader_core_config *get_config() const { return m_config; } void print_cache_stats( FILE *fp, unsigned& dl1_accesses, unsigned& dl1_misses ); + void get_cache_stats(unsigned &read_accesses, unsigned &write_accesses, unsigned &read_misses, unsigned &write_misses, unsigned cache_type); + + void set_icnt_power_stats(unsigned &n_simt_to_mem) const; // debug: void display_simt_state(FILE *fout, int mask ) const; void display_pipeline( FILE *fout, int print_mem, int mask3bit ) const; + void incload_stat(unsigned sid) {m_stats->m_num_loadqueued_insn[sid]++;} + void incstore_stat(unsigned sid) {m_stats->m_num_storequeued_insn[sid]++;} + void incialu_stat(unsigned sid,unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_ialu_acesses[sid]=m_stats->m_num_ialu_acesses[sid]+active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_ialu_acesses[sid]=m_stats->m_num_ialu_acesses[sid]+active_count*latency; + } + } + void inctex_stat(unsigned sid,unsigned active_count,double latency){ + m_stats->m_num_tex_inst[sid]=m_stats->m_num_tex_inst[sid]+active_count*latency; + } + void incimul_stat(unsigned sid,unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_imul_acesses[sid]=m_stats->m_num_imul_acesses[sid]+active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_imul_acesses[sid]=m_stats->m_num_imul_acesses[sid]+active_count*latency; + } + } + void incimul24_stat(unsigned sid,unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_imul24_acesses[sid]=m_stats->m_num_imul24_acesses[sid]+active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_imul24_acesses[sid]=m_stats->m_num_imul24_acesses[sid]+active_count*latency; + } + } + void incimul32_stat(unsigned sid,unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_imul32_acesses[sid]=m_stats->m_num_imul32_acesses[sid]+active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else{ + m_stats->m_num_imul32_acesses[sid]=m_stats->m_num_imul32_acesses[sid]+active_count*latency; + } + //printf("Int_Mul -- Active_count: %d\n",active_count); + } + void incidiv_stat(unsigned sid,unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_idiv_acesses[sid]=m_stats->m_num_idiv_acesses[sid]+active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else { + m_stats->m_num_idiv_acesses[sid]=m_stats->m_num_idiv_acesses[sid]+active_count*latency; + } + } + void incfpalu_stat(unsigned sid,unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_fp_acesses[sid]=m_stats->m_num_fp_acesses[sid]+active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_fp_acesses[sid]=m_stats->m_num_fp_acesses[sid]+active_count*latency; + } + } + void incfpmul_stat(unsigned sid,unsigned active_count,double latency) { + // printf("FP MUL stat increament\n"); + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_fpmul_acesses[sid]=m_stats->m_num_fpmul_acesses[sid]+active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_fpmul_acesses[sid]=m_stats->m_num_fpmul_acesses[sid]+active_count*latency; + } + } + void incfpdiv_stat(unsigned sid,unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_fpdiv_acesses[sid]=m_stats->m_num_fpdiv_acesses[sid]+active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else { + m_stats->m_num_fpdiv_acesses[sid]=m_stats->m_num_fpdiv_acesses[sid]+active_count*latency; + } + } + void inctrans_stat(unsigned sid,unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_trans_acesses[sid]=m_stats->m_num_trans_acesses[sid]+active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else{ + m_stats->m_num_trans_acesses[sid]=m_stats->m_num_trans_acesses[sid]+active_count*latency; + } + } + + void incsfu_stat(unsigned sid,unsigned active_count,double latency) {m_stats->m_num_sfu_acesses[sid]=m_stats->m_num_sfu_acesses[sid]+active_count*latency;} + void incsp_stat(unsigned sid,unsigned active_count,double latency) {m_stats->m_num_sp_acesses[sid]=m_stats->m_num_sp_acesses[sid]+active_count*latency;} + void incmem_stat(unsigned sid,unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_mem_acesses[sid]=m_stats->m_num_mem_acesses[sid]+active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_mem_acesses[sid]=m_stats->m_num_mem_acesses[sid]+active_count*latency; + } + } + void incexecstat(warp_inst_t *&inst); + + void incregfile_reads(unsigned sid,unsigned active_count) {m_stats->m_read_regfile_acesses[sid]=m_stats->m_read_regfile_acesses[sid]+active_count;} + void incregfile_writes(unsigned sid,unsigned active_count){m_stats->m_write_regfile_acesses[sid]=m_stats->m_write_regfile_acesses[sid]+active_count;} + void incnon_rf_operands(unsigned sid,unsigned active_count){m_stats->m_non_rf_operands[sid]=m_stats->m_non_rf_operands[sid]+active_count;} + + void incspactivelanes_stat(unsigned sid,unsigned active_count) {m_stats->m_active_sp_lanes[sid]=m_stats->m_active_sp_lanes[sid]+active_count;} + void incsfuactivelanes_stat(unsigned sid,unsigned active_count) {m_stats->m_active_sfu_lanes[sid]=m_stats->m_active_sfu_lanes[sid]+active_count;} + void incfuactivelanes_stat(unsigned sid,unsigned active_count) {m_stats->m_active_fu_lanes[sid]=m_stats->m_active_fu_lanes[sid]+active_count;} + void incfumemactivelanes_stat(unsigned sid,unsigned active_count) {m_stats->m_active_fu_mem_lanes[sid]=m_stats->m_active_fu_mem_lanes[sid]+active_count;} private: + unsigned inactive_lanes_accesses_sfu(unsigned active_count,double latency){ + return ( ((32-active_count)>>1)*latency) + ( ((32-active_count)>>3)*latency) + ( ((32-active_count)>>3)*latency); + } + unsigned inactive_lanes_accesses_nonsfu(unsigned active_count,double latency){ + return ( ((32-active_count)>>1)*latency); + } + int test_res_bus(int latency); void init_warps(unsigned cta_id, unsigned start_thread, unsigned end_thread); virtual void checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t, unsigned tid); @@ -1362,14 +1643,19 @@ public: m_response_fifo.push_back(mf); } + void get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ) const; unsigned max_cta( const kernel_info_t &kernel ); unsigned get_not_completed() const; void print_not_completed( FILE *fp ) const; unsigned get_n_active_cta() const; + unsigned get_n_active_sms() const; gpgpu_sim *get_gpu() { return m_gpu; } void display_pipeline( unsigned sid, FILE *fout, int print_mem, int mask ); void print_cache_stats( FILE *fp, unsigned& dl1_accesses, unsigned& dl1_misses ) const; + void get_cache_stats(unsigned &read_accesses, unsigned &write_accesses, unsigned &read_misses, unsigned &write_misses, unsigned cache_type) const; + + void set_icnt_stats(unsigned &n_simt_to_mem) const; private: unsigned m_cluster_id; diff --git a/src/gpgpu-sim/stats.h b/src/gpgpu-sim/stats.h index 76304d2..c1b3f2a 100644 --- a/src/gpgpu-sim/stats.h +++ b/src/gpgpu-sim/stats.h @@ -38,13 +38,18 @@ enum mem_stage_access_type { L_MEM_ST, N_MEM_STAGE_ACCESS_TYPE }; - +enum tlb_request_status { + TLB_HIT = 0, + TLB_READY, + TLB_PENDING +}; enum mem_stage_stall_type { NO_RC_FAIL = 0, BK_CONF, MSHR_RC_FAIL, ICNT_RC_FAIL, COAL_STALL, + TLB_STALL, WB_ICNT_RC_FAIL, WB_CACHE_RSRV_FAIL, N_MEM_STAGE_STALL_TYPE diff --git a/src/gpgpu-sim/visualizer.cc b/src/gpgpu-sim/visualizer.cc index c07fbb7..dcb1175 100644 --- a/src/gpgpu-sim/visualizer.cc +++ b/src/gpgpu-sim/visualizer.cc @@ -32,6 +32,8 @@ #include "shader.h" #include "../option_parser.h" #include "mem_latency_stat.h" +#include "power_stat.h" +//#include "../../../mcpat/processor.h" #include "stat-tool.h" #include "gpu-cache.h" @@ -65,7 +67,8 @@ void gpgpu_sim::visualizer_printstat() m_memory_partition_unit[i]->visualizer_print(visualizer_file); m_shader_stats->visualizer_print(visualizer_file); m_memory_stats->visualizer_print(visualizer_file); - + m_power_stats->visualizer_print(visualizer_file); + //proc->visualizer_print(visualizer_file); // other parameters for graphing gzprintf(visualizer_file, "globalcyclecount: %lld\n", gpu_sim_cycle); gzprintf(visualizer_file, "globalinsncount: %lld\n", gpu_sim_insn); |
