diff options
| author | Tor Aamodt <[email protected]> | 2010-10-12 00:46:24 -0800 |
|---|---|---|
| committer | Tor Aamodt <[email protected]> | 2010-10-12 00:46:24 -0800 |
| commit | b0cf792926caf74b393a14e36de676c7afd68164 (patch) | |
| tree | ddcdd107959a1cea591a503e1e73080f14fbfb0f | |
| parent | b3ce70a797756285ea9b15b3e5cf515d8b6a2b63 (diff) | |
1. adding simt_core_cluster, which models a TPC or (for fermi) GPC...
this gives us a place to stick caches shared among shader cores but
on the shader side of the interconnect... maybe move the clock
boundary code here? after integrating booksim 2 code?
2. added a pending write table to ldst_unit rather than scoreboard
... rationale is that ld/st unit needs to process register writes
once it is done it can notify scoreboard once.
3. re-enabled shared memory delay (use pipeline within ldst_unit)
4. re-enabling operand collector writeback for all instruction types
5. disable MSHRs in this change list
passing CUDA 3.1 regression
next? texture cache, then redo mshrs?
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7845]
| -rw-r--r-- | configs/QuadroFX5800/gpgpusim.config | 4 | ||||
| -rw-r--r-- | src/abstract_hardware_model.cc | 1 | ||||
| -rw-r--r-- | src/abstract_hardware_model.h | 31 | ||||
| -rw-r--r-- | src/cuda-sim/instructions.cc | 2 | ||||
| -rw-r--r-- | src/debug.cc | 2 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.cc | 279 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.h | 43 | ||||
| -rw-r--r-- | src/gpgpu-sim/icnt_wrapper.h | 6 | ||||
| -rw-r--r-- | src/gpgpu-sim/l2cache.cc | 27 | ||||
| -rw-r--r-- | src/gpgpu-sim/mem_fetch.cc | 71 | ||||
| -rw-r--r-- | src/gpgpu-sim/mem_fetch.h | 89 | ||||
| -rw-r--r-- | src/gpgpu-sim/scoreboard.cc | 44 | ||||
| -rw-r--r-- | src/gpgpu-sim/scoreboard.h | 13 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 530 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.h | 164 | ||||
| -rw-r--r-- | src/gpgpu-sim/stats.h | 1 | ||||
| -rw-r--r-- | src/gpgpu-sim/visualizer.cc | 6 | ||||
| -rw-r--r-- | src/gpgpusim_entrypoint.cc | 4 | ||||
| -rw-r--r-- | src/intersim/interconnect_interface.cpp | 36 | ||||
| -rw-r--r-- | src/intersim/interconnect_interface.h | 2 |
20 files changed, 800 insertions, 555 deletions
diff --git a/configs/QuadroFX5800/gpgpusim.config b/configs/QuadroFX5800/gpgpusim.config index e5e29bc..97be091 100644 --- a/configs/QuadroFX5800/gpgpusim.config +++ b/configs/QuadroFX5800/gpgpusim.config @@ -4,7 +4,8 @@ -gpgpu_ptx_force_max_capability 11 # high level architecture configuration --gpgpu_n_shader 30 +-gpgpu_n_clusters 10 +-gpgpu_n_cores_per_cluster 3 -gpgpu_n_mem 8 -gpgpu_clock_domains 325.0:650.0:650.0:800.0 @@ -31,7 +32,6 @@ # interconnection -network_mode 1 -inter_config_file icnt_config_quadro_islip.txt --gpu_concentration 3 # dram model config -gpgpu_dram_scheduler 1 diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index 619b9b7..7b67df9 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -3,6 +3,7 @@ #include <algorithm> unsigned mem_access_t::next_access_uid = 0; +unsigned warp_inst_t::sm_next_uid = 0; void move_warp( warp_inst_t *&dst, warp_inst_t *&src ) { diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 41fe025..b94aa48 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -480,6 +480,13 @@ struct shader_core_config unsigned null_bank_func(address_type, unsigned) const { return 1; } unsigned shmem_bank_func(address_type addr, unsigned) const; unsigned dcache_bank_func(address_type add, unsigned line_size) const; + + unsigned n_simt_cores_per_cluster; + unsigned n_simt_clusters; + unsigned n_simt_ejection_buffer_size; + unsigned ldst_unit_response_queue_size; + + unsigned mem2device(unsigned memid) const { return memid + n_simt_clusters; } }; typedef unsigned (shader_core_config::*bank_func_t)(address_type add, unsigned line_size) const; @@ -488,14 +495,22 @@ typedef address_type (*tag_func_t)(address_type add, unsigned line_size); class warp_inst_t: public inst_t { public: // constructors + warp_inst_t() + { + m_uid=0; + m_empty=true; + m_config=NULL; + } warp_inst_t( const struct shader_core_config *config ) { + m_uid=0; assert(config->warp_size<=MAX_WARP_SIZE); m_config=config; m_empty=true; m_isatomic=false; m_per_scalar_thread_valid=false; m_mem_accesses_created=false; + m_cache_hit=false; } // modifiers @@ -519,9 +534,11 @@ public: if( mask & (1<<i) ) warp_active_mask.set(i); } + m_uid = ++sm_next_uid; m_warp_id = warp_id; issue_cycle = cycle; cycles = initiation_interval; + m_cache_hit=false; m_empty=false; } void set_addr( unsigned n, new_addr_type addr ) @@ -564,6 +581,14 @@ public: } } } + void clear_active( std::vector<unsigned> &inactive ) + { + std::vector<unsigned>::iterator i; + for(i=inactive.begin(); i!=inactive.end();i++) { + unsigned t=*i; + warp_active_mask.reset(t); + } + } void set_not_active( unsigned lane_id ) { warp_active_mask.reset(lane_id); @@ -618,7 +643,9 @@ public: void print( FILE *fout ) const; protected: + unsigned m_uid; bool m_empty; + bool m_cache_hit; unsigned long long issue_cycle; unsigned cycles; // used for implementing initiation interval delay bool m_isatomic; @@ -628,17 +655,17 @@ protected: struct per_thread_info { per_thread_info() { - cache_miss=false; memreqaddr=0; } dram_callback_t callback; new_addr_type memreqaddr; // effective address - bool cache_miss; }; bool m_per_scalar_thread_valid; std::vector<per_thread_info> m_per_scalar_thread; bool m_mem_accesses_created; std::vector<mem_access_t> m_accessq; + + static unsigned sm_next_uid; }; void move_warp( warp_inst_t *&dst, warp_inst_t *&src ); diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index e67c779..1ae1919 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -1082,8 +1082,6 @@ void atom_callback( const inst_t* inst, ptx_thread_info* thread ) // Write operation result into global memory // (i.e. copy src1_data to dst) thread->get_global_memory()->write(src1_data.u32,size/8,&op_result.s64,thread,pI); - gpgpu_sim *gpu = thread->get_gpu(); - gpu->decrement_atomic_count(thread->get_hw_sid(),thread->get_hw_wid()); } // atom_impl will now result in a callback being called in mem_ctrl_pop (gpu-sim.c) diff --git a/src/debug.cc b/src/debug.cc index 236870c..49cae96 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -84,6 +84,7 @@ void gpgpu_sim::gpgpu_debug() done = false; } } else { + /* for( unsigned sid=0; sid < m_n_shader; sid++ ) { unsigned hw_thread_id = -1; abort(); @@ -101,6 +102,7 @@ void gpgpu_sim::gpgpu_debug() printf( "\n" ); } } + */ } } diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 9b71aec..4e434c4 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -163,7 +163,6 @@ char * gpgpu_clock_domains; /* GPU uArch parameters */ unsigned int gpu_n_mem_per_ctrlr; -int gpu_n_tpc; char *gpgpu_dwf_hw_opt; unsigned int more_thread = 1; @@ -232,11 +231,19 @@ void gpgpu_sim::reg_options(option_parser_t opp) option_parser_register(opp, "-gpgpu_shader_cta", OPT_UINT32, &m_shader_config->max_cta_per_core, "Maximum number of concurrent CTAs in shader (default 8)", "8"); - - option_parser_register(opp, "-gpgpu_n_shader", OPT_UINT32, &m_n_shader, - "number of shaders in gpu", + option_parser_register(opp, "-gpgpu_n_clusters", OPT_UINT32, &m_shader_config->n_simt_clusters, + "number of processing clusters", + "10"); + option_parser_register(opp, "-gpgpu_n_cores_per_cluster", OPT_UINT32, &m_shader_config->n_simt_cores_per_cluster, + "number of simd cores per cluster", + "3"); + option_parser_register(opp, "-gpgpu_n_cluster_ejection_buffer_size", OPT_UINT32, &m_shader_config->n_simt_ejection_buffer_size, + "number of packets in ejection buffer", "8"); - option_parser_register(opp, "-gpgpu_n_mem", OPT_UINT32, &m_n_mem, + option_parser_register(opp, "-gpgpu_n_ldst_response_buffer_size", OPT_UINT32, &m_shader_config->ldst_unit_response_queue_size, + "number of response packets in ld/st unit ejection buffer", + "2"); + option_parser_register(opp, "-gpgpu_n_mem", OPT_UINT32, &m_memory_config->m_n_mem, "number of memory modules (e.g. memory controllers) in gpu", "8"); option_parser_register(opp, "-gpgpu_n_mem_per_ctrlr", OPT_UINT32, &gpu_n_mem_per_ctrlr, @@ -340,9 +347,6 @@ void gpgpu_sim::reg_options(option_parser_t opp) option_parser_register(opp, "-gpgpu_cflog_interval", OPT_INT32, &gpgpu_cflog_interval, "Interval between each snapshot in control flow logger", "0"); - option_parser_register(opp, "-gpu_concentration", OPT_INT32, &gpu_concentration, - "Number of shader cores per interconnection port (default = 1)", - "1"); option_parser_register(opp, "-gpgpu_local_mem_map", OPT_BOOL, &m_shader_config->gpgpu_local_mem_map, "Mapping from local memory space address to simulated GPU physical address space (default = enabled)", "1"); @@ -396,13 +400,6 @@ void gpgpu_sim::reg_options(option_parser_t opp) ///////////////////////////////////////////////////////////////////////////// -int mem2device(int memid) -{ - return memid + gpu_n_tpc; -} - -///////////////////////////////////////////////////////////////////////////// - void increment_x_then_y_then_z( dim3 &i, const dim3 &bound) { i.x++; @@ -433,18 +430,15 @@ void gpgpu_sim::launch( kernel_info_t &kinfo ) m_running_kernels.push_back(kinfo); } -void gpgpu_sim::next_grid( unsigned &grid_num, class function_info *&entry ) +void gpgpu_sim::next_grid() { - grid_num = ++m_grid_num; m_the_kernel = m_running_kernels.front(); m_running_kernels.pop_front(); - entry = m_the_kernel.entry(); } gpgpu_sim::gpgpu_sim() { m_options_set=false; - m_grid_num=0; m_shader_config = (shader_core_config*)calloc(1,sizeof(shader_core_config)); m_shader_stats = (shader_core_stats*)calloc(1,sizeof(shader_core_stats)); m_memory_config = (memory_config*)calloc(1,sizeof(memory_config)); @@ -474,7 +468,7 @@ void gpgpu_sim::init_gpu() assert( !(m_shader_config->n_thread_per_shader % m_shader_config->warp_size) ); m_shader_stats->num_warps_issuable = (int*) calloc(m_shader_config->max_warps_per_shader+1, sizeof(int)); - m_shader_stats->num_warps_issuable_pershader = (int*) calloc(m_n_shader, sizeof(int)); + m_shader_stats->num_warps_issuable_pershader = (int*) calloc(m_shader_config->n_simt_clusters*m_shader_config->n_simt_cores_per_cluster, sizeof(int)); m_shader_stats->shader_cycle_distro = (unsigned int*) calloc(m_shader_config->warp_size + 3, sizeof(unsigned int)); if(ntok != 2) { @@ -487,32 +481,27 @@ void gpgpu_sim::init_gpu() m_shader_config->pdom_sched_type = m_pdom_sched_type; m_shader_config->gpgpu_n_shmem_bank=16; - m_sc = (shader_core_ctx**) calloc(m_n_shader, sizeof(shader_core_ctx*)); - for (unsigned i=0;i<m_n_shader;i++) { - m_sc[i] = (shader_core_ctx*)calloc(sizeof(shader_core_ctx),1); - m_sc[i] = new (m_sc[i]) shader_core_ctx(this,"sh",i,i/gpu_concentration,m_shader_config,m_shader_stats); - } - - ptx_file_line_stats_create_exposed_latency_tracker(m_n_shader); + 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_shader_stats); - assert(m_n_shader % gpu_concentration == 0); - gpu_n_tpc = m_n_shader / gpu_concentration; + ptx_file_line_stats_create_exposed_latency_tracker(num_shader()); - addrdec_setnchip(m_n_mem); - m_memory_partition_unit = new memory_partition_unit*[m_n_mem]; - for (unsigned i=0;i<m_n_mem;i++) + addrdec_setnchip(m_memory_config->m_n_mem); + m_memory_partition_unit = new memory_partition_unit*[m_memory_config->m_n_mem]; + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) m_memory_partition_unit[i] = new memory_partition_unit(i, m_memory_config); - m_memory_stats = new memory_stats_t(m_n_mem,m_n_shader,m_shader_config,m_memory_config); - for (unsigned i=0;i<m_n_mem;i++) + m_memory_stats = new memory_stats_t(m_memory_config->m_n_mem,num_shader(),m_shader_config,m_memory_config); + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) m_memory_partition_unit[i]->set_stats(m_memory_stats); - concurrent_row_access = (unsigned int**) calloc(m_n_mem, sizeof(unsigned int*)); - num_activates = (unsigned int**) calloc(m_n_mem, sizeof(unsigned int*)); - row_access = (unsigned int**) calloc(m_n_mem, sizeof(unsigned int*)); - max_conc_access2samerow = (unsigned int**) calloc(m_n_mem, sizeof(unsigned int*)); - max_servicetime2samerow = (unsigned int**) calloc(m_n_mem, sizeof(unsigned int*)); + concurrent_row_access = (unsigned int**) calloc(m_memory_config->m_n_mem, sizeof(unsigned int*)); + num_activates = (unsigned int**) calloc(m_memory_config->m_n_mem, sizeof(unsigned int*)); + row_access = (unsigned int**) calloc(m_memory_config->m_n_mem, sizeof(unsigned int*)); + max_conc_access2samerow = (unsigned int**) calloc(m_memory_config->m_n_mem, sizeof(unsigned int*)); + max_servicetime2samerow = (unsigned int**) calloc(m_memory_config->m_n_mem, sizeof(unsigned int*)); - for (unsigned i=0;i<m_n_mem ;i++ ) { + for (unsigned i=0;i<m_memory_config->m_n_mem ;i++ ) { concurrent_row_access[i] = (unsigned int*) calloc(m_memory_config->gpu_mem_n_bk, sizeof(unsigned int)); row_access[i] = (unsigned int*) calloc(m_memory_config->gpu_mem_n_bk, sizeof(unsigned int)); num_activates[i] = (unsigned int*) calloc(m_memory_config->gpu_mem_n_bk, sizeof(unsigned int)); @@ -520,11 +509,9 @@ void gpgpu_sim::init_gpu() max_servicetime2samerow[i] = (unsigned int*) calloc(m_memory_config->gpu_mem_n_bk, sizeof(unsigned int)); } - m_memory_stats = new memory_stats_t(m_n_mem,m_n_shader,m_shader_config,m_memory_config); + m_memory_stats = new memory_stats_t(m_memory_config->m_n_mem,num_shader(),m_shader_config,m_memory_config); - m_shader_stats->max_return_queue_length = (unsigned int*) calloc(m_n_shader, sizeof(unsigned int)); - - icnt_init(gpu_n_tpc, m_n_mem,m_shader_config); + icnt_init(m_shader_config->n_simt_clusters, m_memory_config->m_n_mem,m_shader_config); time_vector_create(NUM_MEM_REQ_STAT,MR_2SH_ICNT_INJECTED); fprintf(stdout, "GPU performance model initialization complete.\n"); @@ -598,7 +585,6 @@ void gpgpu_sim::reinit_clock_domains(void) unsigned int gpgpu_sim::run_gpu_sim() { // run a CUDA grid on the GPU microarchitecture simulator - int grid_num = m_grid_num; kernel_info_t &entry = m_the_kernel; size_t program_size = get_kernel_code_size(entry.entry()); @@ -617,9 +603,9 @@ unsigned int gpgpu_sim::run_gpu_sim() m_shader_stats->gpu_completed_thread = 0; reinit_clock_domains(); - set_param_gpgpu_num_shaders(m_n_shader); - for (unsigned i=0;i<m_n_shader;i++) - m_sc[i]->reinit(0,m_shader_config->n_thread_per_shader,true); + set_param_gpgpu_num_shaders(num_shader()); + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) + m_cluster[i]->reinit(); if (gpu_max_cta_opt != 0) { g_total_cta_left = gpu_max_cta_opt; } else { @@ -640,23 +626,23 @@ unsigned int gpgpu_sim::run_gpu_sim() } // initialize the control-flow, memory access, memory latency logger - create_thread_CFlogger( m_n_shader, m_shader_config->n_thread_per_shader, program_size, 0, gpgpu_cflog_interval ); - shader_CTA_count_create( m_n_shader, gpgpu_cflog_interval); + create_thread_CFlogger( num_shader(), m_shader_config->n_thread_per_shader, program_size, 0, gpgpu_cflog_interval ); + shader_CTA_count_create( num_shader(), gpgpu_cflog_interval); if (gpgpu_cflog_interval != 0) { - insn_warp_occ_create( m_n_shader, m_shader_config->warp_size, program_size ); - shader_warp_occ_create( m_n_shader, m_shader_config->warp_size, gpgpu_cflog_interval); - shader_mem_acc_create( m_n_shader, m_n_mem, 4, gpgpu_cflog_interval); - shader_mem_lat_create( m_n_shader, gpgpu_cflog_interval); - shader_cache_access_create( m_n_shader, 3, gpgpu_cflog_interval); + insn_warp_occ_create( num_shader(), m_shader_config->warp_size, program_size ); + shader_warp_occ_create( num_shader(), m_shader_config->warp_size, gpgpu_cflog_interval); + shader_mem_acc_create( num_shader(), m_memory_config->m_n_mem, 4, gpgpu_cflog_interval); + shader_mem_lat_create( num_shader(), gpgpu_cflog_interval); + shader_cache_access_create( num_shader(), 3, gpgpu_cflog_interval); set_spill_interval (gpgpu_cflog_interval * 40); } // calcaulte the max cta count and cta size for local memory address mapping - m_shader_config->gpu_max_cta_per_shader = m_sc[0]->max_cta(entry.entry()); + m_shader_config->gpu_max_cta_per_shader = m_cluster[0]->max_cta(entry.entry()); //gpu_max_cta_per_shader is limited by number of CTAs if not enough - if (m_the_kernel.num_blocks() < m_shader_config->gpu_max_cta_per_shader*m_n_shader) { - m_shader_config->gpu_max_cta_per_shader = (m_the_kernel.num_blocks() / m_n_shader); - if (m_the_kernel.num_blocks() % m_n_shader) + if (m_the_kernel.num_blocks() < m_shader_config->gpu_max_cta_per_shader*num_shader()) { + m_shader_config->gpu_max_cta_per_shader = (m_the_kernel.num_blocks() / num_shader()); + if (m_the_kernel.num_blocks() % num_shader()) m_shader_config->gpu_max_cta_per_shader++; } unsigned int gpu_cta_size = m_the_kernel.threads_per_cta(); @@ -670,10 +656,10 @@ unsigned int gpgpu_sim::run_gpu_sim() while (not_completed || mem_busy || icnt2mem_busy) { cycle(); not_completed = 0; - for (unsigned i=0;i<m_n_shader;i++) - not_completed += m_sc[i]->get_not_completed(); + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) + not_completed += m_cluster[i]->get_not_completed(); mem_busy = 0; - for (unsigned i=0;i<m_n_mem;i++) + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) mem_busy += m_memory_partition_unit[i]->busy(); icnt2mem_busy = icnt_busy(); if (gpu_max_cycle && (gpu_tot_sim_cycle + gpu_sim_cycle) >= gpu_max_cycle) @@ -683,14 +669,13 @@ unsigned int gpgpu_sim::run_gpu_sim() if (gpu_deadlock_detect && gpu_deadlock) break; } - m_memory_stats->memlatstat_lat_pw(m_n_shader,m_shader_config->n_thread_per_shader,m_shader_config->warp_size); + m_memory_stats->memlatstat_lat_pw(num_shader(),m_shader_config->n_thread_per_shader,m_shader_config->warp_size); gpu_tot_sim_cycle += gpu_sim_cycle; gpu_tot_sim_insn += gpu_sim_insn; gpu_tot_completed_thread += m_shader_stats->gpu_completed_thread; ptx_file_line_stats_write_file(); - printf("stats for grid: %d\n", grid_num); gpu_print_stat(); if (g_network_mode) { interconnect_stats(); @@ -699,10 +684,10 @@ unsigned int gpgpu_sim::run_gpu_sim() printf("----------------------------END-of-Interconnect-DETAILS-------------------------" ); } if (m_memory_config->gpgpu_memlatency_stat & GPU_MEMLATSTAT_QUEUELOGS ) { - for (unsigned i=0;i<m_n_mem;i++) + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) m_memory_partition_unit[i]->queue_latency_log_dump(stdout); if (m_memory_config->gpgpu_cache_dl2_opt) { - for(unsigned i=0; i<m_n_mem; i++) + for(unsigned i=0; i<m_memory_config->m_n_mem; i++) m_memory_partition_unit[i]->L2c_log(DUMPLOG); L2c_latency_log_dump(); } @@ -715,8 +700,8 @@ unsigned int gpgpu_sim::run_gpu_sim() (unsigned) gpu_sim_insn_last_update, (unsigned) (gpu_tot_sim_cycle-gpu_sim_cycle), (unsigned) (gpu_sim_cycle - gpu_sim_insn_last_update )); unsigned num_cores=0; - for (unsigned i=0;i<m_n_shader;i++) { - unsigned not_completed = m_sc[i]->get_not_completed(); + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { + unsigned not_completed = m_cluster[i]->get_not_completed(); if( not_completed ) { if ( !num_cores ) { printf("GPGPU-Sim uArch: DEADLOCK shader cores no longer committing instructions [core(# threads)]:\n" ); @@ -730,7 +715,7 @@ unsigned int gpgpu_sim::run_gpu_sim() } } printf("\n"); - for (unsigned i=0;i<m_n_mem;i++) { + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) { bool busy = m_memory_partition_unit[i]->busy(); if( busy ) printf("GPGPU-Sim uArch DEADLOCK: memory partition %u busy\n", i ); @@ -769,12 +754,7 @@ void gpgpu_sim::gpu_print_stat() const // performance counter that are not local to one shader shader_print_accstats(stdout); - m_memory_stats->memlatstat_print(m_n_mem,m_memory_config->gpu_mem_n_bk); - printf("max return queue length = "); - for (unsigned i=0;i<m_n_shader;i++) { - printf("%d ", m_shader_stats->max_return_queue_length[i]); - } - printf("\n"); + m_memory_stats->memlatstat_print(m_memory_config->m_n_mem,m_memory_config->gpu_mem_n_bk); // merge misses printf("L1 read misses = %d\n", m_shader_stats->L1_read_miss); printf("L1 write misses = %d\n", m_shader_stats->L1_write_miss); @@ -802,9 +782,9 @@ void gpgpu_sim::gpu_print_stat() const //printf("\n"); if (m_memory_config->gpgpu_cache_dl2_opt) { - m_memory_stats->L2c_print_stat( m_n_mem ); + m_memory_stats->L2c_print_stat( m_memory_config->m_n_mem ); } - for (unsigned i=0;i<m_n_mem;i++) + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) m_memory_partition_unit[i]->print(stdout); /* unsigned a,m; @@ -940,94 +920,6 @@ void gpgpu_sim::mem_instruction_stats(warp_inst_t &inst) } } -//////////////////////////////////////////////////////////////////////////////////// -// Wrapper function for shader cores' memory system: -//////////////////////////////////////////////////////////////////////////////////// - -// Check the memory system for buffer availability -unsigned char gpgpu_sim::fq_has_buffer(unsigned long long int addr, int bsize, bool write, int sid ) -{ - //requests should be single always now - int rsize = bsize; - //maintain similar functionality with fq_push, if its a read, bsize is the load size, not the request's size - if (!write) { - rsize = READ_PACKET_SIZE; - } - return check_icnt_has_buffer(addr, rsize, sid); -} - -unsigned char gpgpu_sim::check_icnt_has_buffer(unsigned long long int addr, int bsize, int sid ) -{ - int tpc_id = sid / gpu_concentration; - return icnt_has_buffer(tpc_id, bsize); -} - -int gpgpu_sim::issue_mf_from_fq(mem_fetch *mf) -{ - // stats - if (mf->get_is_write()) m_shader_stats->made_write_mfs++; - else m_shader_stats->made_read_mfs++; - switch (mf->get_mem_acc()) { - case CONST_ACC_R: m_shader_stats->gpgpu_n_mem_const++; break; - case TEXTURE_ACC_R: m_shader_stats->gpgpu_n_mem_texture++; break; - case GLOBAL_ACC_R: m_shader_stats->gpgpu_n_mem_read_global++; break; - case GLOBAL_ACC_W: m_shader_stats->gpgpu_n_mem_write_global++; break; - case LOCAL_ACC_R: m_shader_stats->gpgpu_n_mem_read_local++; break; - case LOCAL_ACC_W: m_shader_stats->gpgpu_n_mem_write_local++; break; - case INST_ACC_R: m_shader_stats->gpgpu_n_mem_read_inst++; break; - default: assert(0); - } - - unsigned destination = mf->get_tlx_addr().chip; - unsigned tpc_id = mf->get_tpc(); - mf->set_status(IN_ICNT2MEM,MR_ICNT_PUSHED,gpu_sim_cycle+gpu_tot_sim_cycle); - if (!mf->get_is_write()) { - mf->set_type(RD_REQ); - icnt_push(tpc_id, mem2device(destination), (void*)mf, mf->get_ctrl_size() ); - } else { - mf->set_type(WT_REQ); - icnt_push(tpc_id, mem2device(destination), (void*)mf, mf->size()); - gpgpu_n_sent_writes++; - } - return 0; -} - -void shader_core_ctx::fill_shd_L1_with_new_line(mem_fetch * mf) -{ - // When the data arrives, it flags all the appropriate MSHR - // entries accordingly (by checking the address in each entry ) - if ( mf->isinst() ) { - m_L1I->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle); - m_warp[mf->get_wid()].clear_imiss_pending(); - delete mf->get_mshr(); - delete mf; - } else { - m_ldst_unit->fill(mf); - } - freed_read_mfs++; -} - -void shader_core_ctx::store_ack( class mem_fetch *mf ) -{ - unsigned warp_id = mf->get_wid(); - m_warp[warp_id].dec_store_req(); -} - -void gpgpu_sim::fq_pop(int tpc_id) -{ - mem_fetch *mf = (mem_fetch*) icnt_pop(tpc_id); - if (!mf) - return; - assert(mf->get_type() == REPLY_DATA); - mf->set_status(IN_ICNT2SHADER,MR_2SH_FQ_POP,gpu_sim_cycle+gpu_tot_sim_cycle); - if (mf->get_is_write()) { - m_sc[mf->get_sid()]->store_ack(mf); - delete mf; - } else { - m_memory_stats->memlatstat_read_done(mf,m_shader_config->max_warps_per_shader); - m_sc[mf->get_sid()]->fill_shd_L1_with_new_line(mf); - } -} //////////////////////////////////////////////////////////////////////////////////////////////// @@ -1074,7 +966,7 @@ void shader_core_ctx::issue_block2core( kernel_info_t &kernel ) for (unsigned i = start_thread; i<end_thread; i++) { m_thread[i].m_cta_id = free_cta_hw_id; unsigned warp_id = i/m_config->warp_size; - nthreads_in_block += ptx_sim_init_thread(kernel,&m_thread[i].m_functional_model_thread_state,m_sid,i,cta_size-(i-start_thread),m_config->n_thread_per_shader,this,free_cta_hw_id,warp_id,m_gpu); + nthreads_in_block += ptx_sim_init_thread(kernel,&m_thread[i].m_functional_model_thread_state,m_sid,i,cta_size-(i-start_thread),m_config->n_thread_per_shader,this,free_cta_hw_id,warp_id,m_cluster->get_gpu()); warps.set( warp_id ); } assert( nthreads_in_block > 0 && nthreads_in_block <= m_config->n_thread_per_shader); // should be at least one, but less than max @@ -1230,26 +1122,26 @@ void gpgpu_sim::cycle() { int clock_mask = next_clock_domain(); - // shader core loading (pop from ICNT into shader core) follows CORE clock if (clock_mask & CORE ) { - for (int i=0;i<gpu_n_tpc;i++) - fq_pop(i); + // shader core loading (pop from ICNT into core) follows CORE clock + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) + m_cluster[i]->icnt_cycle(); } if (clock_mask & ICNT) { // pop from memory controller to interconnect - for (unsigned i=0;i<m_n_mem;i++) { + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) { mem_fetch* mf = m_memory_partition_unit[i]->top(); if (mf) { mf->set_status(IN_ICNT2SHADER,MR_2SH_ICNT_PUSHED,gpu_sim_cycle+gpu_tot_sim_cycle); unsigned response_size = mf->get_is_write()?mf->get_ctrl_size():mf->size(); - if ( icnt_has_buffer( mem2device(i), response_size ) ) { + if ( ::icnt_has_buffer( m_shader_config->mem2device(i), response_size ) ) { if (!mf->get_is_write()) mf->set_return_timestamp(gpu_sim_cycle+gpu_tot_sim_cycle); else { freed_L1write_mfs++; gpgpu_n_processed_writes++; } - icnt_push( mem2device(i), mf->get_tpc(), mf, response_size ); + ::icnt_push( m_shader_config->mem2device(i), mf->get_tpc(), mf, response_size ); m_memory_partition_unit[i]->pop(); } else { gpu_stall_icnt2sh++; @@ -1261,24 +1153,24 @@ void gpgpu_sim::cycle() } if (clock_mask & DRAM) { - for (unsigned i=0;i<m_n_mem;i++) + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) m_memory_partition_unit[i]->issueCMD(); // Issue the dram command (scheduler + delay model) } // L2 operations follow L2 clock domain if (clock_mask & L2) { - for (unsigned i=0;i<m_n_mem;i++) + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) m_memory_partition_unit[i]->cache_cycle(); } if (clock_mask & ICNT) { - for (unsigned i=0;i<m_n_mem;i++) { + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) { if ( m_memory_partition_unit[i]->full() ) { gpu_stall_dramfull++; continue; } // move memory request from interconnect into memory partition (if memory controller not backed up) - mem_fetch* mf = (mem_fetch*) icnt_pop( mem2device(i) ); + mem_fetch* mf = (mem_fetch*) icnt_pop( m_shader_config->mem2device(i) ); m_memory_partition_unit[i]->push( mf, gpu_sim_cycle + gpu_tot_sim_cycle ); } icnt_transfer(); @@ -1286,9 +1178,9 @@ void gpgpu_sim::cycle() if (clock_mask & CORE) { // L1 cache + shader core pipeline stages - for (unsigned i=0;i<m_n_shader;i++) { - if (m_sc[i]->get_not_completed() || more_thread) { - m_sc[i]->cycle(); + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { + if (m_cluster[i]->get_not_completed() || more_thread) { + m_cluster[i]->core_cycle(); } } if( g_single_step && ((gpu_sim_cycle+gpu_tot_sim_cycle) >= g_single_step) ) { @@ -1298,9 +1190,9 @@ void gpgpu_sim::cycle() if( g_interactive_debugger_enabled ) gpgpu_debug(); - for (unsigned i=0;i<m_n_shader && more_thread;i++) { - if ( ( (m_sc[i]->get_n_active_cta()+1) <= m_sc[i]->max_cta(m_the_kernel.entry()) ) && g_total_cta_left ) { - m_sc[i]->issue_block2core( m_the_kernel ); + for (unsigned i=0;i<m_shader_config->n_simt_clusters && more_thread;i++) { + if ( ( (m_cluster[i]->get_n_active_cta()+1) <= m_cluster[i]->max_cta(m_the_kernel.entry()) ) && g_total_cta_left ) { + m_cluster[i]->issue_block2core( m_the_kernel ); if (!g_total_cta_left) more_thread = 0; assert( g_total_cta_left > -1 ); @@ -1310,9 +1202,9 @@ void gpgpu_sim::cycle() // Flush the caches once all of threads are completed. if (gpgpu_flush_cache) { int all_threads_complete = 1 ; - for (unsigned i=0;i<m_n_shader;i++) { - if (m_sc[i]->get_not_completed() == 0) - m_sc[i]->cache_flush(); + 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 ; } @@ -1320,7 +1212,7 @@ void gpgpu_sim::cycle() printf("Flushed L2 caches...\n"); if (m_memory_config->gpgpu_cache_dl2_opt) { int dlc = 0; - for (unsigned i=0;i<m_n_mem;i++) { + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) { dlc = m_memory_partition_unit[i]->flushL2(); assert (dlc == 0); // need to model actual writes to DRAM here printf("Dirty lines flushed from L2 %d is %d\n", i, dlc ); @@ -1345,11 +1237,11 @@ void gpgpu_sim::cycle() (unsigned)days,(unsigned)hrs,(unsigned)minutes,(unsigned)sec, ctime(&curr_time)); fflush(stdout); - m_memory_stats->memlatstat_lat_pw(m_n_shader,m_shader_config->n_thread_per_shader,m_shader_config->warp_size); + m_memory_stats->memlatstat_lat_pw(num_shader(),m_shader_config->n_thread_per_shader,m_shader_config->warp_size); visualizer_printstat(); if (gpgpu_runtime_stat && (gpu_runtime_stat_flag != 0) ) { if (gpu_runtime_stat_flag & GPU_RSTAT_BW_STAT) { - for (unsigned i=0;i<m_n_mem;i++) + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) m_memory_partition_unit[i]->print_stat(stdout); printf("maxmrqlatency = %d \n", m_memory_stats->max_mrq_latency); printf("maxmflatency = %d \n", m_memory_stats->max_mf_latency); @@ -1371,7 +1263,7 @@ void gpgpu_sim::cycle() } if (gpu_runtime_stat_flag & GPU_RSTAT_SCHED ) { printf("Average Num. Warps Issuable per Shader:\n"); - for (unsigned i=0;i<m_n_shader;i++) { + for (unsigned i=0;i<num_shader();i++) { printf("%2.2f ", (float) m_shader_stats->num_warps_issuable_pershader[i]/ gpu_stat_sample_freq); m_shader_stats->num_warps_issuable_pershader[i] = 0; } @@ -1380,7 +1272,7 @@ void gpgpu_sim::cycle() } } - for (unsigned i=0;i<m_n_mem;i++) + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) m_memory_stats->acc_mrq_length[i] += m_memory_partition_unit[i]->dram_que_length(); if (!(gpu_sim_cycle % 20000)) { // deadlock detection @@ -1417,17 +1309,17 @@ void gpgpu_sim::dump_pipeline( int mask, int s, int m ) const printf("Dumping pipeline state...\n"); if(!mask) mask = 0xFFFFFFFF; - for (unsigned i=0;i<m_n_shader;i++) { + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { if(s != -1) { i = s; } - if(mask&1) m_sc[i]->display_pipeline(stdout, 1, mask & 0x2E ); + if(mask&1) m_cluster[sid_to_cluster(i)]->display_pipeline(i,stdout,1,mask & 0x2E); if(s != -1) { break; } } if(mask&0x10000) { - for (unsigned i=0;i<m_n_mem;i++) { + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) { if(m != -1) { i=m; } @@ -1447,3 +1339,4 @@ void memory_partition_unit::visualizer_print( gzFile visualizer_file ) { m_dram->visualizer_print(visualizer_file); } + diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h index 5dbdf51..51ebd58 100644 --- a/src/gpgpu-sim/gpu-sim.h +++ b/src/gpgpu-sim/gpu-sim.h @@ -113,6 +113,7 @@ struct memory_config { bool gpgpu_memlatency_stat; unsigned gpgpu_dram_buswidth; unsigned gpgpu_dram_burst_length; + unsigned m_n_mem; }; // global config @@ -140,12 +141,10 @@ public: void set_prop( struct cudaDeviceProp *prop ); void launch( kernel_info_t &kinfo ); - void next_grid( unsigned &grid_num, class function_info *&entry ); + void next_grid(); unsigned run_gpu_sim(); - unsigned char fq_has_buffer(unsigned long long int addr, int bsize, bool write, int sid ); - void decrement_atomic_count( unsigned sid, unsigned wid ); void get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ); const kernel_info_t &the_kernel() const { return m_the_kernel; } @@ -156,10 +155,9 @@ public: const struct cudaDeviceProp *get_prop() const; enum divergence_support_t simd_model() const; - unsigned num_shader() const { return m_n_shader; } + unsigned num_shader() const { return m_shader_config->n_simt_clusters*m_shader_config->n_simt_cores_per_cluster; } unsigned threads_per_core() const; void mem_instruction_stats( class warp_inst_t &inst); - int issue_mf_from_fq(class mem_fetch *mf); void gpu_print_stat() const; void dump_pipeline( int mask, int s, int m ) const; @@ -174,9 +172,7 @@ private: void reinit_clock_domains(void); int next_clock_domain(void); - unsigned char check_icnt_has_buffer(unsigned long long int addr, int bsize, int sid ); void cycle(); - void fq_pop(int tpc_id); void L2c_options(class OptionParser *opp); void L2c_print_cache_stat() const; void L2c_print_debug(); @@ -188,15 +184,28 @@ private: void print_shader_cycle_distro( FILE *fout ) const; void gpgpu_debug(); + unsigned sid_to_cluster( unsigned sid ) const; - // data - class shader_core_ctx **m_sc; +///// data ///// + + class simt_core_cluster **m_cluster; class memory_partition_unit **m_memory_partition_unit; - unsigned m_grid_num; kernel_info_t m_the_kernel; std::list<kernel_info_t> m_running_kernels; + // time of next rising edge + double core_time; + double icnt_time; + double dram_time; + double l2_time; + + // debug + bool gpu_deadlock; + + //// configuration parameters //// + bool m_options_set; + // clock domains - frequency double core_freq; double icnt_freq; @@ -209,24 +218,12 @@ private: double dram_period; double l2_period; - // time of next rising edge - double core_time; - double icnt_time; - double dram_time; - double l2_time; - - // configuration parameters - bool m_options_set; struct cudaDeviceProp *m_cuda_properties; struct shader_core_config *m_shader_config; struct memory_config *m_memory_config; - unsigned int m_n_shader; - unsigned int m_n_mem; - int gpu_concentration; int m_pdom_sched_type; - // options bool gpu_deadlock_detect; int m_ptx_convert_to_ptxplus; int m_ptx_save_converted_ptxplus; @@ -239,8 +236,6 @@ private: unsigned long long gpu_tot_completed_thread; unsigned long long last_gpu_sim_insn; - // debug - bool gpu_deadlock; public: unsigned long long gpu_sim_insn; unsigned long long gpu_tot_sim_insn; diff --git a/src/gpgpu-sim/icnt_wrapper.h b/src/gpgpu-sim/icnt_wrapper.h index 26e394b..ff8905d 100644 --- a/src/gpgpu-sim/icnt_wrapper.h +++ b/src/gpgpu-sim/icnt_wrapper.h @@ -68,9 +68,9 @@ #define ICNT_WRAPPER_H // functional interface to the interconnect -typedef int (*icnt_has_buffer_p)(unsigned int input, unsigned int size); -typedef void (*icnt_push_p)(unsigned int input, unsigned int output, void* data, unsigned int size); -typedef void* (*icnt_pop_p)(unsigned int output); +typedef bool (*icnt_has_buffer_p)(unsigned input, unsigned int size); +typedef void (*icnt_push_p)(unsigned input, unsigned output, void* data, unsigned int size); +typedef void* (*icnt_pop_p)(unsigned output); typedef void (*icnt_transfer_p)( ); typedef unsigned (*icnt_busy_p)( ); typedef void (*icnt_drain_p)( ); diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index 411f452..29903ea 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -525,11 +525,12 @@ bool memory_partition_unit::L2c_write_back( unsigned long long int addr, int bsi (unsigned)-1/*sid*/, (unsigned)-1/*tpc*/, (unsigned)-1/*wid*/, - NULL,true, + (unsigned)-1/*mshr_id*/, + NULL/*inst*/, + true/*write*/, partial_write_mask_t(), L2_WRBK_ACC, - L2_WTBK_DATA, - -1/*pc*/); + L2_WTBK_DATA ); made_write_mfs++; L2todram_wbqueue->push(mf,gpu_sim_cycle); gpgpu_n_sent_writes++; @@ -635,7 +636,7 @@ void memory_stats_t::print( FILE *fp ) void gpgpu_sim::L2c_print_cache_stat() const { unsigned i, j, k; - for (i=0,j=0,k=0;i<m_n_mem;i++) + for (i=0,j=0,k=0;i<m_memory_config->m_n_mem;i++) m_memory_partition_unit[i]->L2c_print_cache_stat(k,j); printf("L2 Cache Total Miss Rate = %0.3f\n", (float)j/k); } @@ -645,46 +646,46 @@ void gpgpu_sim::L2c_print_debug() unsigned i; printf(" "); - for (i=0;i<m_n_mem;i++) + for (i=0;i<m_memory_config->m_n_mem;i++) printf(" dram[%d]", i); printf("\n"); printf("cbtoL2 queue length ="); - for (i=0;i<m_n_mem;i++) + for (i=0;i<m_memory_config->m_n_mem;i++) printf("%8d", m_memory_partition_unit[i]->get_cbtoL2queue_length() ); printf("\n"); printf("cbtoL2 write queue length ="); - for (i=0;i<m_n_mem;i++) + for (i=0;i<m_memory_config->m_n_mem;i++) printf("%8d", m_memory_partition_unit[i]->get_cbtoL2writequeue_length()); printf("\n"); printf("L2tocb queue length ="); - for (i=0;i<m_n_mem;i++) { + for (i=0;i<m_memory_config->m_n_mem;i++) { printf("%8d", m_memory_partition_unit[i]->get_L2tocbqueue_length()); } printf("\n"); printf("dramtoL2 queue length ="); - for (i=0;i<m_n_mem;i++) { + for (i=0;i<m_memory_config->m_n_mem;i++) { printf("%8d", m_memory_partition_unit[i]->get_dramtoL2queue_length()); } printf("\n"); printf("dramtoL2 write queue length ="); - for (i=0;i<m_n_mem;i++) { + for (i=0;i<m_memory_config->m_n_mem;i++) { printf("%8d", m_memory_partition_unit[i]->get_dramtoL2writequeue_length()); } printf("\n"); printf("L2todram queue length ="); - for (i=0;i<m_n_mem;i++) { + for (i=0;i<m_memory_config->m_n_mem;i++) { printf("%8d", m_memory_partition_unit[i]->get_L2todramqueue_length()); } printf("\n"); printf("L2todram writeback queue length ="); - for (i=0;i<m_n_mem;i++) { + for (i=0;i<m_memory_config->m_n_mem;i++) { printf("%8d", m_memory_partition_unit[i]->get_L2todram_wbqueue_length()); } printf("\n"); @@ -722,7 +723,7 @@ unsigned memory_partition_unit::flushL2() void gpgpu_sim::L2c_latency_log_dump() { - for (unsigned i=0;i<m_n_mem;i++) + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) m_memory_partition_unit[i]->L2c_latency_log_dump(); } diff --git a/src/gpgpu-sim/mem_fetch.cc b/src/gpgpu-sim/mem_fetch.cc index 1a4af1e..50442c8 100644 --- a/src/gpgpu-sim/mem_fetch.cc +++ b/src/gpgpu-sim/mem_fetch.cc @@ -77,70 +77,65 @@ mem_fetch::mem_fetch( new_addr_type addr, unsigned sid, unsigned tpc, unsigned wid, - class mshr_entry * mshr, - bool write, + unsigned mshr_id, + warp_inst_t *inst, + bool write, partial_write_mask_t partial_write_mask, enum mem_access_type mem_acc, - enum mf_type type, - address_type pc ) + enum mf_type type ) { - class mem_fetch *mf = this; - mf->request_uid = sm_next_mf_request_uid++; + m_request_uid = sm_next_mf_request_uid++; - mf->addr = addr; - mf->nbytes_L1 = data_size; - mf->ctrl_size = ctrl_size; - mf->sid = sid; - mf->wid = wid; - mf->tpc = tpc; - mf->mshr = mshr; - mf->m_write = write; - addrdec_tlx(addr,&mf->tlx); - mf->mem_acc = mem_acc; - mf->type = type; - mf->pc = pc; - mf->timestamp = gpu_sim_cycle + gpu_tot_sim_cycle; - mf->timestamp2 = 0; + m_addr = addr; + m_data_size = data_size; + m_ctrl_size = ctrl_size; + m_sid = sid; + m_wid = wid; + m_tpc = tpc; + m_mshr_id = mshr_id; + if( inst ) m_inst = *inst; + m_write = write; + addrdec_tlx(addr,&m_raw_addr); + m_mem_acc = mem_acc; + m_type = type; + m_timestamp = gpu_sim_cycle + gpu_tot_sim_cycle; + m_timestamp2 = 0; + + m_status = INITIALIZED; } void mem_fetch::print( FILE *fp ) const { - fprintf(fp," mf: uid=%6u, addr=0x%08llx, sid=%u, wid=%u, pc=0x%04x, %s, bank=%u, ", - request_uid, addr, sid, wid, pc, (m_write?"write":"read "), tlx.bk); - if( mshr ) mshr->print(fp); + fprintf(fp," mf: uid=%6u, addr=0x%08llx, sid=%u, wid=%u, mshr_id=%u, %s, bank=%u, ", + m_request_uid, m_addr, m_sid, m_wid, m_mshr_id, (m_write?"write":"read "), m_raw_addr.bk); + if( !m_inst.empty() ) m_inst.print(fp); else fprintf(fp,"\n"); } void mem_fetch::set_status( enum mshr_status status, enum mem_req_stat stat, unsigned long long cycle ) { - if ( mshr ) { - mshr->set_status(status); - time_vector_update(request_uid,stat,cycle,type); - } + m_status = status; } bool mem_fetch::isatomic() const { - if( !mshr ) return false; - return mshr->isatomic(); + if( m_inst.empty() ) return false; + return m_inst.isatomic(); } void mem_fetch::do_atomic() { - mshr->do_atomic(); -} - -bool mem_fetch::isinst() const -{ - return (mshr==NULL)?false:mshr->isinst(); + m_inst.do_atomic(); } bool mem_fetch::istexture() const -{ - return (mshr==NULL)?false:mshr->istexture(); +{ + if( m_inst.empty() ) return false; + return m_inst.space.get_type() == tex_space; } bool mem_fetch::isconst() const { - return (mshr==NULL)?false:mshr->isconst(); + if( m_inst.empty() ) return false; + return m_inst.space.get_type() == const_space; } diff --git a/src/gpgpu-sim/mem_fetch.h b/src/gpgpu-sim/mem_fetch.h index 0aab2cb..31a47da 100644 --- a/src/gpgpu-sim/mem_fetch.h +++ b/src/gpgpu-sim/mem_fetch.h @@ -103,6 +103,7 @@ enum mshr_status { IN_L2TOCBQUEUE_HIT, IN_L2TOCBQUEUE_MISS, IN_ICNT2SHADER, + IN_CLUSTER2SHADER, FETCHED, NUM_MSHR_STATUS }; @@ -138,66 +139,72 @@ public: unsigned sid, unsigned tpc, unsigned wid, - class mshr_entry * mshr, - bool write, + unsigned mshr_id, + warp_inst_t *inst, + bool write, partial_write_mask_t partial_write_mask, enum mem_access_type mem_acc, - enum mf_type type, - address_type pc ); + enum mf_type type ); void set_status( enum mshr_status status, enum mem_req_stat stat, unsigned long long cycle ); - void set_type( enum mf_type t ) { type=t; } + void set_type( enum mf_type t ) { m_type=t; } void do_atomic(); void print( FILE *fp ) const; - const addrdec_t &get_tlx_addr() const { return tlx; } - unsigned get_data_size() const { return nbytes_L1; } - unsigned get_ctrl_size() const { return ctrl_size; } - unsigned size() const { return nbytes_L1+ctrl_size; } - new_addr_type get_addr() const { return addr; } - class mshr_entry *get_mshr() { return mshr; } + const addrdec_t &get_tlx_addr() const { return m_raw_addr; } + unsigned get_data_size() const { return m_data_size; } + unsigned get_ctrl_size() const { return m_ctrl_size; } + unsigned size() const { return m_data_size+m_ctrl_size; } + new_addr_type get_addr() const { return m_addr; } + unsigned get_mshr() { return m_mshr_id; } bool get_is_write() const { return m_write; } - unsigned get_request_uid() const { return request_uid; } - unsigned get_sid() const { return sid; } - unsigned get_tpc() const { return tpc; } - unsigned get_wid() const { return wid; } - bool isinst() const; + unsigned get_request_uid() const { return m_request_uid; } + unsigned get_sid() const { return m_sid; } + unsigned get_tpc() const { return m_tpc; } + unsigned get_wid() const { return m_wid; } bool istexture() const; bool isconst() const; - enum mf_type get_type() const { return type; } + enum mf_type get_type() const { return m_type; } bool isatomic() const; - void set_return_timestamp( unsigned t ) { timestamp2=t; } - void set_icnt_receive_time( unsigned t ) { icnt_receive_time=t; } - unsigned get_timestamp() const { return timestamp; } - unsigned get_return_timestamp() const { return timestamp2; } - unsigned get_icnt_receive_time() const { return icnt_receive_time; } - enum mem_access_type get_mem_acc() const { return mem_acc; } - address_type get_pc() const { return pc; } + void set_return_timestamp( unsigned t ) { m_timestamp2=t; } + void set_icnt_receive_time( unsigned t ) { m_icnt_receive_time=t; } + unsigned get_timestamp() const { return m_timestamp; } + unsigned get_return_timestamp() const { return m_timestamp2; } + unsigned get_icnt_receive_time() const { return m_icnt_receive_time; } + enum mem_access_type get_mem_acc() const { return m_mem_acc; } + address_type get_pc() const { return m_inst.empty()?-1:m_inst.pc; } + const warp_inst_t &get_inst() { return m_inst; } + enum mshr_status get_status() const { return m_status; } private: - // request origination - unsigned request_uid; - address_type pc; - unsigned sid; - unsigned tpc; - unsigned wid; - class mshr_entry* mshr; + // request source information + unsigned m_request_uid; + unsigned m_sid; + unsigned m_tpc; + unsigned m_wid; + unsigned m_mshr_id; + + // where is the request now? + enum mshr_status m_status; // request type, address, size, mask bool m_write; - enum mem_access_type mem_acc; - enum mf_type type; - new_addr_type addr; - addrdec_t tlx; - partial_write_mask_t write_mask; - unsigned nbytes_L1; - unsigned ctrl_size; + enum mem_access_type m_mem_acc; + enum mf_type m_type; + new_addr_type m_addr; + addrdec_t m_raw_addr; + partial_write_mask_t m_write_mask; + unsigned m_data_size; // bytes + unsigned m_ctrl_size; // statistics - unsigned timestamp; // set to gpu_sim_cycle+gpu_tot_sim_cycle at struct creation - unsigned timestamp2; // set to gpu_sim_cycle+gpu_tot_sim_cycle when pushed onto icnt to shader; only used for reads - unsigned icnt_receive_time; // set to gpu_sim_cycle + interconnect_latency when fixed icnt latency mode is enabled + unsigned m_timestamp; // set to gpu_sim_cycle+gpu_tot_sim_cycle at struct creation + unsigned m_timestamp2; // set to gpu_sim_cycle+gpu_tot_sim_cycle when pushed onto icnt to shader; only used for reads + unsigned m_icnt_receive_time; // set to gpu_sim_cycle + interconnect_latency when fixed icnt latency mode is enabled + + // requesting instruction + warp_inst_t m_inst; static unsigned sm_next_mf_request_uid; }; diff --git a/src/gpgpu-sim/scoreboard.cc b/src/gpgpu-sim/scoreboard.cc index 3484714..f3029f1 100644 --- a/src/gpgpu-sim/scoreboard.cc +++ b/src/gpgpu-sim/scoreboard.cc @@ -19,61 +19,47 @@ Scoreboard::Scoreboard( unsigned sid, unsigned n_warps ) } // Print scoreboard contents -void Scoreboard::printContents() +void Scoreboard::printContents() const { printf("scoreboard contents (sid=%d): \n", m_sid); for(unsigned i=0; i<reg_table.size(); i++) { if(reg_table[i].size() == 0 ) continue; - printf(" wid = %d: ", i); - std::set<int>::iterator it; - for ( it=reg_table[i].begin() ; it != reg_table[i].end(); it++ ) - printf("%d ", *it); + printf(" wid = %2d: ", i); + std::set<unsigned>::const_iterator it; + for( it=reg_table[i].begin() ; it != reg_table[i].end(); it++ ) + printf("%u ", *it); printf("\n"); } } - -// Mark register as write-pending void Scoreboard::reserveRegister(unsigned wid, unsigned regnum) { if( !(reg_table[wid].find(regnum) == reg_table[wid].end()) ){ printf("Error: trying to reserve an already reserved register (sid=%d, wid=%d, regnum=%d).", m_sid, wid, regnum); - assert(reg_table[wid].find(regnum) == reg_table[wid].end()); + abort(); } - reg_table[wid].insert(regnum); } - // Unmark register as write-pending void Scoreboard::releaseRegister(unsigned wid, unsigned regnum) { - if( !(reg_table[wid].find(regnum) != reg_table[wid].end()) ) { - printf("Error: trying to release an unreserved register (sid=%d, wid=%d, regnum=%d).", m_sid, wid, regnum); - assert(reg_table[wid].find(regnum) != reg_table[wid].end()); - } + if( !(reg_table[wid].find(regnum) != reg_table[wid].end()) ) + return; reg_table[wid].erase(regnum); } - -// Reserve registers for an instruction -void Scoreboard::reserveRegisters(unsigned wid, const class inst_t* inst) +void Scoreboard::reserveRegisters(const class warp_inst_t* inst) { - // Reserve registers - if(inst->out[0] > 0) reserveRegister(wid, inst->out[0]); - if(inst->out[1] > 0) reserveRegister(wid, inst->out[1]); - if(inst->out[2] > 0) reserveRegister(wid, inst->out[2]); - if(inst->out[3] > 0) reserveRegister(wid, inst->out[3]); + for( unsigned r=0; r < 4; r++) + if(inst->out[r] > 0) reserveRegister(inst->warp_id(), inst->out[r]); } // Release registers for an instruction void Scoreboard::releaseRegisters(const class warp_inst_t *inst) { - unsigned wid = inst->warp_id(); - if(inst->out[0] > 0) releaseRegister(wid, inst->out[0]); - if(inst->out[1] > 0) releaseRegister(wid, inst->out[1]); - if(inst->out[2] > 0) releaseRegister(wid, inst->out[2]); - if(inst->out[3] > 0) releaseRegister(wid, inst->out[3]); + for( unsigned r=0; r < 4; r++) + if(inst->out[r] > 0) releaseRegister(inst->warp_id(), inst->out[r]); } /** @@ -82,7 +68,7 @@ void Scoreboard::releaseRegisters(const class warp_inst_t *inst) * @return * true if WAW or RAW hazard (no WAR since in-order issue) **/ -bool Scoreboard::checkCollision( unsigned wid, const class inst_t *inst ) +bool Scoreboard::checkCollision( unsigned wid, const class inst_t *inst ) const { // Get list of all input and output registers std::set<int> inst_regs; @@ -100,7 +86,7 @@ bool Scoreboard::checkCollision( unsigned wid, const class inst_t *inst ) if(inst->ar2 > 0) inst_regs.insert(inst->ar2); // Check for collision, get the intersection of reserved registers and instruction registers - std::set<int>::iterator it2; + std::set<int>::const_iterator it2; for ( it2=inst_regs.begin() ; it2 != inst_regs.end(); it2++ ) if(reg_table[wid].find(*it2) != reg_table[wid].end()) { return true; diff --git a/src/gpgpu-sim/scoreboard.h b/src/gpgpu-sim/scoreboard.h index 4e1c154..1b7235d 100644 --- a/src/gpgpu-sim/scoreboard.h +++ b/src/gpgpu-sim/scoreboard.h @@ -20,22 +20,21 @@ class Scoreboard { public: Scoreboard( unsigned sid, unsigned n_warps ); - void printContents(); - - void reserveRegisters(unsigned wid, const inst_t *inst); + void reserveRegisters(const warp_inst_t *inst); void releaseRegisters(const warp_inst_t *inst); + void releaseRegister(unsigned wid, unsigned regnum); - bool checkCollision(unsigned wid, const inst_t *inst); + bool checkCollision(unsigned wid, const inst_t *inst) const; bool pendingWrites(unsigned wid) const; + void printContents() const; private: void reserveRegister(unsigned wid, unsigned regnum); - void releaseRegister(unsigned wid, unsigned regnum); unsigned m_sid; // keeps track of pending writes to registers - // indexed by warp id - std::vector< std::set<int> > reg_table; + // indexed by warp id, reg_id => pending write count + std::vector< std::set<unsigned> > reg_table; }; diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index f298a67..ae62b97 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -79,6 +79,9 @@ #include "mem_fetch.h" #include "mem_latency_stat.h" #include "visualizer.h" +#include "../intersim/statwraper.h" +#include "../intersim/interconnect_interface.h" +#include "icnt_wrapper.h" #include <string.h> #include <limits.h> @@ -102,6 +105,7 @@ static const char* MSHR_Status_str[] = { "IN_L2TOCBQUEUE_HIT", "IN_L2TOCBQUEUE_MISS", "IN_ICNT2SHADER", + "IN_CLUSTER2SHADER", "FETCHED", }; @@ -146,9 +150,7 @@ bool mshr_lookup::can_merge(mshr_entry * mshr) if (mshr->isatomic()) return false; // can't merge a atomic operation bool interwarp_mshr_merge = m_shader_config->gpgpu_interwarp_mshr_merge & GLOBAL_MSHR_MERGE; - if (mshr->isinst()) - interwarp_mshr_merge=true; - else if (mshr->istexture()) + if (mshr->istexture()) interwarp_mshr_merge = m_shader_config->gpgpu_interwarp_mshr_merge & TEX_MSHR_MERGE; else if (mshr->isconst()) interwarp_mshr_merge = m_shader_config->gpgpu_interwarp_mshr_merge & CONST_MSHR_MERGE; @@ -235,9 +237,15 @@ std::list<mshr_entry*> &mshr_shader_unit::choose_return_queue() return m_mshr_return_queue; } -void mshr_shader_unit::mshr_return_from_mem(mshr_entry *mshr) +void mshr_shader_unit::mshr_return_from_mem(unsigned mshr_id) { - mshr->set_status( FETCHED ); + if(mshr_id == -1) { + return; + } + mshr_entry *mshr = &m_mshrs[mshr_id]; + mshr->set_fetched(); + mem_fetch *mf = mshr->get_mf(); + if( mf ) mf->set_status( FETCHED, MR_RETURN_Q, gpu_sim_cycle+gpu_tot_sim_cycle ); if ( not mshr->istexture() ) { //place in return queue mshr->add_to_queue( m_mshr_return_queue ); @@ -266,9 +274,10 @@ void mshr_shader_unit::print(FILE* fp) mshr_entry *mshr = *m; mshr->print(fp); } - fprintf(fp,"\nTotal outstanding memory requests = %u\n", num_outstanding ); + fprintf(fp,"outstanding memory requests = %u\n", num_outstanding ); } + std::list<unsigned> shader_core_ctx::get_regs_written( const inst_t &fvt ) const { std::list<unsigned> result; @@ -280,31 +289,22 @@ std::list<unsigned> shader_core_ctx::get_regs_written( const inst_t &fvt ) const return result; } -int log2i(int n) { - int lg; - lg = -1; - while (n) { - n>>=1;lg++; - } - return lg; -} - -shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, - const char *name, +shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, + class simt_core_cluster *cluster, unsigned shader_id, unsigned tpc_id, struct shader_core_config *config, struct shader_core_stats *stats ) : m_barriers( config->max_warps_per_shader, config->max_cta_per_core ) { - m_gpu = gpu; + m_gpu = gpu; + m_cluster = cluster; m_config = config; m_stats = stats; unsigned warp_size=config->warp_size; config->max_sfu_latency = 32; config->max_sp_latency = 32; - m_name = name; m_sid = shader_id; m_tpc = tpc_id; @@ -364,7 +364,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_dispatch_port[1] = ID_OC_SFU; m_issue_port[1] = OC_EX_SFU; - m_ldst_unit = new ldst_unit( m_gpu, this, &m_pipeline_reg[EX_WB], config, m_stats, m_sid, m_tpc ); + m_ldst_unit = new ldst_unit( m_cluster, this, &m_operand_collector, m_scoreboard, config, m_stats, m_sid, m_tpc ); m_fu[2] = m_ldst_unit; m_dispatch_port[2] = ID_OC_MEM; m_issue_port[2] = OC_EX_MEM; @@ -406,12 +406,6 @@ void shader_core_ctx::init_warps( unsigned cta_id, unsigned start_thread, unsign } } -// initalize the pipeline stage register to nops -void shader_core_ctx::clear_stage_reg(int stage) -{ - m_pipeline_reg[stage]->clear(); -} - // return the next pc of a thread address_type shader_core_ctx::next_pc( int tid ) const { @@ -501,9 +495,15 @@ void pdom_warp_ctx_t::pdom_update_warp_mask() assert(scheduled_warp->m_stack_top < m_warp_size * 2); } +unsigned gpgpu_sim::sid_to_cluster( unsigned sid ) const +{ + return sid / m_shader_config->n_simt_cores_per_cluster; +} + void gpgpu_sim::get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ) { - m_sc[sid]->get_pdom_stack_top_info(tid,pc,rpc); + unsigned cluster_id = 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 ) @@ -615,27 +615,23 @@ void shader_core_ctx::fetch() enum cache_request_status status = m_L1I->access( (unsigned long long)pc, 0, gpu_sim_cycle, &wb ); if( status != HIT ) { unsigned req_size = READ_PACKET_SIZE; - if( m_gpu->fq_has_buffer(ppc, req_size, false, m_sid) ) { + if( !m_cluster->icnt_injection_buffer_full(ppc, req_size, false) ) { m_last_warp_fetched=warp_id; - mshr_entry *mshr = new mshr_entry(); - mshr->init(ppc,false,instruction_space,warp_id); - mem_fetch *mf = new mem_fetch(pc, req_size, READ_PACKET_SIZE, m_sid, m_tpc, warp_id, - mshr, + (unsigned)-1/*mshr_id*/, + NULL/*we don't have an instruction yet*/, false, NO_PARTIAL_WRITE, INST_ACC_R, - RD_REQ, - pc); - mshr->set_mf(mf); - m_gpu->issue_mf_from_fq(mf); + RD_REQ ); + m_cluster->icnt_inject_request_packet(mf); - m_warp[warp_id].set_imiss_pending(mshr); + m_warp[warp_id].set_imiss_pending(); m_warp[warp_id].set_last_fetch(gpu_sim_cycle); } } else { @@ -658,7 +654,8 @@ void shader_core_ctx::func_exec_inst( warp_inst_t &inst ) if( inst.has_callback(t) ) m_warp[inst.warp_id()].inc_n_atomic(); if (inst.space.is_local() && (inst.is_load() || inst.is_store())) - inst.set_addr(t, translate_local_memaddr(inst.get_addr(t), tid, m_gpu->num_shader()) ); + inst.set_addr(t, translate_local_memaddr(inst.get_addr(t), tid, + m_config->n_simt_clusters*m_config->n_simt_cores_per_cluster) ); if ( ptx_thread_done(tid) ) { m_warp[inst.warp_id()].inc_n_completed(); m_warp[inst.warp_id()].ibuffer_flush(); @@ -679,7 +676,7 @@ void shader_core_ctx::issue_warp( warp_inst_t *&pipe_reg, const warp_inst_t *nex else if( next_inst->op == MEMORY_BARRIER_OP ) set_at_memory_barrier(warp_id); m_pdom_warp[warp_id]->pdom_update_warp_mask(); - m_scoreboard->reserveRegisters(warp_id, next_inst); + m_scoreboard->reserveRegisters(pipe_reg); m_warp[warp_id].set_next_pc(next_inst->pc + next_inst->isize); } @@ -806,7 +803,7 @@ mshr_entry* mshr_shader_unit::add_mshr(mem_access_t &access, warp_inst_t* pinst) if (mergehit) { mergehit->merge(mshr); if (mergehit->fetched()) - mshr_return_from_mem(mshr); + mshr_return_from_mem(mshr->get_id()); } m_mshr_lookup.mshr_fast_lookup_insert(mshr); } @@ -1035,7 +1032,7 @@ mem_stage_stall_type ldst_unit::send_mem_request(warp_inst_t &inst, mem_access_t // It is possible to do this writeback in the same cycle as the access request, this may not be realistic. if (access.need_wb) { unsigned req_size = m_config->gpgpu_cache_dl1_linesize + WRITE_PACKET_SIZE; - if ( !m_gpu->fq_has_buffer(access.wb_addr, req_size, true, m_sid) ) { + if ( m_cluster->icnt_injection_buffer_full(access.wb_addr, req_size, true) ) { m_stats->gpu_stall_sh2icnt++; return WB_ICNT_RC_FAIL; } @@ -1044,31 +1041,40 @@ mem_stage_stall_type ldst_unit::send_mem_request(warp_inst_t &inst, mem_access_t READ_PACKET_SIZE, m_sid, m_tpc, - -1, + -1/*wid*/, + -1/*mshr id*/, NULL, true, NO_PARTIAL_WRITE, inst.space.is_local()?LOCAL_ACC_W:GLOBAL_ACC_W, //space of cache line is same as new request - WT_REQ, - -1); - m_gpu->issue_mf_from_fq(mf); + WT_REQ ); + m_cluster->icnt_inject_request_packet(mf); + inst.clear_active(access.warp_indices); m_stats->L1_writeback++; access.need_wb = false; } bool is_write = inst.is_store(); mem_access_type access_type; + bool requires_mshr = false; switch(inst.space.get_type()) { case const_space: - case param_space_kernel: access_type = CONST_ACC_R; break; - case tex_space: access_type = TEXTURE_ACC_R; break; - case global_space: access_type = is_write? GLOBAL_ACC_W: GLOBAL_ACC_R; break; + case param_space_kernel: + access_type = CONST_ACC_R; + break; + case tex_space: + access_type = TEXTURE_ACC_R; + break; + case global_space: + access_type = is_write? GLOBAL_ACC_W: GLOBAL_ACC_R; + break; case local_space: - case param_space_local: access_type = is_write? LOCAL_ACC_W: LOCAL_ACC_R; break; + case param_space_local: + access_type = is_write? LOCAL_ACC_W: LOCAL_ACC_R; + break; default: assert(0); break; } //reserve mshr - bool requires_mshr = (!is_write); if (requires_mshr && !access.reserved_mshr) { if (not m_mshr_unit->has_mshr(1)) return MSHR_RC_FAIL; @@ -1087,7 +1093,7 @@ mem_stage_stall_type ldst_unit::send_mem_request(warp_inst_t &inst, mem_access_t else request_size += WRITE_PACKET_SIZE + WRITE_MASK_SIZE; //plain write } - if ( !m_gpu->fq_has_buffer(access.addr, request_size, is_write, m_sid) ) { + if ( m_cluster->icnt_injection_buffer_full(access.addr, request_size, is_write) ) { // can't allocate icnt m_stats->gpu_stall_sh2icnt++; return ICNT_RC_FAIL; @@ -1105,21 +1111,29 @@ mem_stage_stall_type ldst_unit::send_mem_request(warp_inst_t &inst, mem_access_t if (write_mask.count() != access.req_size) m_stats->gpgpu_n_partial_writes++; } + unsigned mshr_id = access.reserved_mshr?access.reserved_mshr->get_id():-1; + warp_inst_t inst_copy = inst; + inst_copy.set_active(access.warp_indices); mem_fetch *mf = new mem_fetch(access.addr, request_size, is_write?WRITE_PACKET_SIZE:READ_PACKET_SIZE, m_sid, m_tpc, warp_id, - access.reserved_mshr, + mshr_id, + &inst_copy, is_write, write_mask, access_type, - is_write?WT_REQ:RD_REQ, - inst.pc); + is_write?WT_REQ:RD_REQ); if( access.reserved_mshr ) access.reserved_mshr->set_mf(mf); - m_gpu->issue_mf_from_fq(mf); + m_cluster->icnt_inject_request_packet(mf); + if( inst.is_load() ) { + for( unsigned r=0; r < 4; r++) + if(inst.out[r] > 0) + m_pending_writes[inst.warp_id()][inst.out[r]]++; + } } return NO_RC_FAIL; } @@ -1136,6 +1150,7 @@ void shader_core_ctx::writeback() m_gpu->gpu_sim_insn += pipe_reg->active_count(); pipe_reg->clear(); } + m_ldst_unit->writeback(); } bool ldst_unit::shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type) @@ -1176,18 +1191,19 @@ mem_stage_stall_type ldst_unit::process_memory_access_queue( ldst_unit::cache_ch break; unsigned current_order = inst.accessq_back().order; // consume all requests of the same "order" but stop if we hit a structural hazard - while ((!inst.accessq_empty()) && inst.accessq_back().order == current_order && hazard_cond == NO_RC_FAIL) { + while( !inst.accessq_empty() && inst.accessq_back().order == current_order && hazard_cond == NO_RC_FAIL) { hazard_cond = (this->*cache_check)(inst,inst.accessq_back()); if (hazard_cond != NO_RC_FAIL) break; // can't complete this request this cycle. - if (! inst.accessq_back().cache_hit){ + if ( !inst.accessq_back().cache_hit ){ if (mem_req_count < memory_send_max) { mem_req_count++; - hazard_cond = send_mem_request(inst,inst.accessq_back()); // attemp to get mshr, icnt, send; + hazard_cond = send_mem_request(inst,inst.accessq_back()); } else hazard_cond = COAL_STALL; // not really a coal stall, its a too many memory request stall; - if ( hazard_cond != NO_RC_FAIL) break; //can't complete this request this cycle. - } + if ( hazard_cond != NO_RC_FAIL) + break; //can't complete this request this cycle. + } inst.accessq_pop_back(); } } @@ -1236,7 +1252,6 @@ bool ldst_unit::texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, return inst.accessq_empty(); //done if empty. } - mem_stage_stall_type ldst_unit::dcache_check(warp_inst_t &inst, mem_access_t& access) { // Global memory (data cache) checks the cache for each access at the time it is processed. @@ -1255,7 +1270,8 @@ mem_stage_stall_type ldst_unit::dcache_check(warp_inst_t &inst, mem_access_t& ac return WB_CACHE_RSRV_FAIL; } access.cache_hit = (status == HIT); //if HIT_W_WT then still send to memory so "MISS" - if (status == MISS_W_WB) access.need_wb = true; + if (status == MISS_W_WB) + access.need_wb = true; if (status == WB_HIT_ON_MISS && inst.is_store()) { //write has hit a reserved cache line @@ -1320,15 +1336,14 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea return inst.accessq_empty(); //done if empty. } +bool ldst_unit::response_buffer_full() const +{ + return m_response_fifo.size() >= m_config->ldst_unit_response_queue_size; +} + void ldst_unit::fill( mem_fetch *mf ) { - m_mshr_unit->mshr_return_from_mem(mf->get_mshr()); - if (mf->istexture()) - m_L1T->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle); - else if (mf->isconst()) - m_L1C->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle); - else if (!m_config->gpgpu_no_dl1) - m_L1D->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle); + m_response_fifo.push_back(mf); } void ldst_unit::flush() @@ -1376,20 +1391,23 @@ void ldst_unit::generate_mem_accesses(warp_inst_t &inst) case param_space_unclassified: abort(); break; default: break; // non-memory operations } - m_gpu->mem_instruction_stats(inst); + m_cluster->mem_instruction_stats(inst); inst.set_mem_accesses_created(); } -ldst_unit::ldst_unit( gpgpu_sim *gpu, +ldst_unit::ldst_unit( simt_core_cluster *cluster, shader_core_ctx *core, - warp_inst_t **result_port, + opndcoll_rfu_t *operand_collector, + Scoreboard *scoreboard, shader_core_config *config, shader_core_stats *stats, unsigned sid, - unsigned tpc ) : simd_function_unit(result_port,config) + unsigned tpc ) : pipelined_simd_unit(NULL,config,6) { - m_gpu = gpu; + m_cluster = cluster; m_core = core; + m_operand_collector = operand_collector; + m_scoreboard = scoreboard; m_stats = stats; m_sid = sid; m_tpc = tpc; @@ -1407,21 +1425,69 @@ ldst_unit::ldst_unit( gpgpu_sim *gpu, config->gpgpu_cache_dl1_linesize = m_L1D->get_line_sz(); config->gpgpu_cache_texl1_linesize = m_L1T->get_line_sz(); config->gpgpu_cache_constl1_linesize = m_L1C->get_line_sz(); - m_gpu->ptx_set_tex_cache_linesize(m_L1T->get_line_sz()); + m_cluster->get_gpu()->ptx_set_tex_cache_linesize(m_L1T->get_line_sz()); m_mshr_unit = new mshr_shader_unit(m_config); m_mem_rc = NO_RC_FAIL; } +void ldst_unit::writeback() +{ + mshr_entry *m = m_mshr_unit->return_head(); + if( m ) m_mshr_unit->pop_return_head(); + + if( !m_pipeline_reg[0]->empty() ) { + // shared memory has priority + if( m_operand_collector->writeback(*m_pipeline_reg[0]) ) { + m_scoreboard->releaseRegisters(m_pipeline_reg[0]); + m_core->dec_inst_in_pipeline(m_pipeline_reg[0]->warp_id()); + m_pipeline_reg[0]->clear(); + } + } + + if( !m_response_fifo.empty() ) { + mem_fetch *mf = m_response_fifo.front(); + if( mf->get_is_write() ) { + m_core->store_ack(mf); + m_response_fifo.pop_front(); + } else { + const warp_inst_t &inst = mf->get_inst(); + if( m_operand_collector->writeback(inst) ) { + m_response_fifo.pop_front(); + if( mf->isatomic() ) + m_core->decrement_atomic_count(mf->get_wid(),inst.active_count()); + for( unsigned r=0; r < 4; r++ ) { + if( inst.out[r] > 0 ) { + assert( m_pending_writes[inst.warp_id()][inst.out[r]] > 0 ); + unsigned still_pending = --m_pending_writes[inst.warp_id()][inst.out[r]]; + if( !still_pending ) { + m_pending_writes[inst.warp_id()].erase(inst.out[r]); + m_scoreboard->releaseRegister( inst.warp_id(), inst.out[r] ); + } + } + } + m_mshr_unit->mshr_return_from_mem(mf->get_mshr()); + if (mf->istexture()) + m_L1T->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle); + else if (mf->isconst()) + m_L1C->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle); + else if (!m_config->gpgpu_no_dl1) + m_L1D->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle); + delete mf; + } + } + } +} + void ldst_unit::cycle() { - mshr_entry *m = m_mshr_unit->return_head(); - if( m ) { - delete m->get_mf(); - m_mshr_unit->pop_return_head(); - } + for( unsigned stage=0; (stage+1)<m_pipeline_depth; stage++ ) + if( m_pipeline_reg[stage]->empty() && !m_pipeline_reg[stage+1]->empty() ) + move_warp(m_pipeline_reg[stage], m_pipeline_reg[stage+1]); + // process new memory requests warp_inst_t &pipe_reg = *m_dispatch_reg; generate_mem_accesses(pipe_reg); + enum mem_stage_stall_type rc_fail = NO_RC_FAIL; mem_stage_access_type type; bool done = true; @@ -1436,30 +1502,65 @@ void ldst_unit::cycle() m_stats->gpu_stall_shd_mem_breakdown[type][rc_fail]++; return; } - if( !(*m_result_port)->empty() ) - return; // writeback stalled - move_warp(*m_result_port,m_dispatch_reg); + + if( !pipe_reg.empty() ) { + unsigned warp_id = pipe_reg.warp_id(); + if( pipe_reg.is_load() ) { + if( pipe_reg.space.get_type() == shared_space ) { + if( m_pipeline_reg[5]->empty() ) { + // new shared memory request + move_warp(m_pipeline_reg[5],m_dispatch_reg); + m_dispatch_reg->clear(); + } + } else { + if( pipe_reg.active_count() > 0 ) { + if( !m_operand_collector->writeback(pipe_reg) ) + return; + } + + bool pending_requests=false; + for( unsigned r=0; r<4; r++ ) { + unsigned reg_id = pipe_reg.out[r]; + if( reg_id > 0 ) { + if( m_pending_writes[warp_id].find(reg_id) != m_pending_writes[warp_id].end() ) { + assert( m_pending_writes[warp_id][reg_id] > 0 ); + pending_requests=true; + break; + } + } + } + if( !pending_requests ) + m_scoreboard->releaseRegisters(m_dispatch_reg); + m_core->dec_inst_in_pipeline(warp_id); + m_dispatch_reg->clear(); + } + } else { + // stores exit pipeline here + m_core->dec_inst_in_pipeline(warp_id); + m_dispatch_reg->clear(); + } + } } void shader_core_ctx::register_cta_thread_exit(int tid ) { - shader_core_ctx *shader = this; unsigned padded_cta_size = m_gpu->the_kernel().threads_per_cta(); if (padded_cta_size%m_config->warp_size) padded_cta_size = ((padded_cta_size/m_config->warp_size)+1)*(m_config->warp_size); int cta_num = tid/padded_cta_size; - assert( shader->m_cta_status[cta_num] > 0 ); - shader->m_cta_status[cta_num]--; - if (!shader->m_cta_status[cta_num]) { - shader->m_n_active_cta--; - shader->deallocate_barrier(cta_num); - shader_CTA_count_unlog(shader->m_sid, 1); - printf("GPGPU-Sim uArch: Shader %d finished CTA #%d (%lld,%lld)\n", shader->m_sid, cta_num, gpu_sim_cycle, gpu_tot_sim_cycle ); + assert( m_cta_status[cta_num] > 0 ); + m_cta_status[cta_num]--; + if (!m_cta_status[cta_num]) { + m_n_active_cta--; + deallocate_barrier(cta_num); + shader_CTA_count_unlog(m_sid, 1); + printf("GPGPU-Sim uArch: Shader %d finished CTA #%d (%lld,%lld)\n", m_sid, cta_num, gpu_sim_cycle, gpu_tot_sim_cycle ); } } void gpgpu_sim::shader_print_runtime_stat( FILE *fout ) { + /* fprintf(fout, "SHD_INSN: "); for (unsigned i=0;i<m_n_shader;i++) fprintf(fout, "%u ",m_sc[i]->get_num_sim_insn()); @@ -1477,11 +1578,13 @@ void gpgpu_sim::shader_print_runtime_stat( FILE *fout ) for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) fprintf(fout, "%d ", m_sc[0]->get_thread_n_insn(i) ); fprintf(fout, "\n"); + */ } void gpgpu_sim::shader_print_l1_miss_stat( FILE *fout ) { + /* fprintf(fout, "THD_INSN_AC: "); for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) fprintf(fout, "%d ", m_sc[0]->get_thread_n_insn_ac(i)); @@ -1530,6 +1633,7 @@ void gpgpu_sim::shader_print_l1_miss_stat( FILE *fout ) } } fprintf(fout, "\n"); + */ } void warp_inst_t::print( FILE *fout ) const @@ -1598,6 +1702,20 @@ void ldst_unit::print(FILE *fout) const fprintf(fout,"\n"); } m_mshr_unit->print(fout); + fprintf(fout,"Pending register writes:\n"); + std::map<unsigned/*warp_id*/, std::map<unsigned/*regnum*/,unsigned/*count*/> >::const_iterator w; + for( w=m_pending_writes.begin(); w!=m_pending_writes.end(); w++ ) { + unsigned warp_id = w->first; + const std::map<unsigned/*regnum*/,unsigned/*count*/> &warp_info = w->second; + if( warp_info.empty() ) + continue; + fprintf(fout," w%2u : ", warp_id ); + std::map<unsigned/*regnum*/,unsigned/*count*/>::const_iterator r; + for( r=warp_info.begin(); r!=warp_info.end(); ++r ) { + fprintf(fout," %u(%u)", r->first, r->second ); + } + fprintf(fout,"\n"); + } } void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, int mask ) @@ -1696,7 +1814,7 @@ unsigned int shader_core_ctx::max_cta( class function_info *kernel ) } if (result < 1) { - printf ("Error: max_cta_per_shader(\"%s\") returning %d. Kernel requires more resources than shader has?\n", m_name, result); + printf ("Error: max_cta_per_shader(\"sid=%u\") returning %d. Kernel requires more resources than shader has?\n", m_sid, result); abort(); } return result; @@ -1966,10 +2084,40 @@ void shader_core_ctx::deallocate_barrier( unsigned cta_id ) m_barriers.deallocate_barrier(cta_id); } -void shader_core_ctx::decrement_atomic_count( unsigned wid ) +void shader_core_ctx::decrement_atomic_count( unsigned wid, unsigned n ) +{ + assert( m_warp[wid].get_n_atomic() >= n ); + m_warp[wid].dec_n_atomic(n); +} + + +bool shader_core_ctx::fetch_unit_response_buffer_full() const +{ + return false; +} + +void shader_core_ctx::accept_fetch_response( mem_fetch *mf ) { - assert( m_warp[wid].get_n_atomic() > 0 ); - m_warp[wid].dec_n_atomic(); + m_L1I->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle); + m_warp[mf->get_wid()].clear_imiss_pending(); + delete mf; +} + +bool shader_core_ctx::ldst_unit_response_buffer_full() +{ + return m_ldst_unit->response_buffer_full(); +} + +void shader_core_ctx::accept_ldst_unit_response(mem_fetch * mf) +{ + m_ldst_unit->fill(mf); + //freed_read_mfs++; +} + +void shader_core_ctx::store_ack( class mem_fetch *mf ) +{ + unsigned warp_id = mf->get_wid(); + m_warp[warp_id].dec_store_req(); } bool shd_warp_t::done() @@ -2077,7 +2225,6 @@ void mshr_entry::init( new_addr_type address, bool wr, memory_space_t space, uns { static unsigned next_request_uid = 1; m_request_uid = next_request_uid++; - m_status = INITIALIZED; m_addr = address; m_mf = NULL; m_merged_on_other_reqest = false; @@ -2087,23 +2234,11 @@ void mshr_entry::init( new_addr_type address, bool wr, memory_space_t space, uns m_islocal = space.is_local(); m_isconst = space.is_const(); m_istexture = space==tex_space; + m_isatomic = false; m_insts.clear(); m_warp_id = warp_id; } -void mshr_entry::set_status( enum mshr_status status ) -{ - mshr_entry * req = this; - while (req) { - req->m_status = status; - req = req->m_merged_requests; - } -#if DEBUGL1MISS -#define CACHE_TAG_OF_64(x) ((x) & (~((unsigned long long int)64 - 1))) - printf("cycle %d Addr %x %d \n",gpu_sim_cycle,CACHE_TAG_OF_64(m_addr),status); -#endif -} - void mshr_entry::print(FILE *fp) const { fprintf(fp, "MSHR(%u): w%2u req uid=%5u, %s (0x%llx) merged:%d status:%s ", @@ -2113,7 +2248,7 @@ void mshr_entry::print(FILE *fp) const (m_iswrite)? "store" : "load ", m_addr, (m_merged_requests != NULL || m_merged_on_other_reqest), - MSHR_Status_str[m_status]); + m_mf?MSHR_Status_str[ m_mf->get_status() ]:"???"); if ( m_mf ) ptx_print_insn( m_mf->get_pc(), fp ); fprintf(fp,"\n"); @@ -2165,22 +2300,20 @@ int register_bank(int regnum, int wid, unsigned num_banks, unsigned bank_warp_sh return bank % num_banks; } -bool opndcoll_rfu_t::writeback( const warp_inst_t &warp ) +bool opndcoll_rfu_t::writeback( const warp_inst_t &inst ) { - assert( !warp.empty() ); - std::list<unsigned> regs = m_shader->get_regs_written(warp); + assert( !inst.empty() ); + std::list<unsigned> regs = m_shader->get_regs_written(inst); std::list<unsigned>::iterator r; - unsigned last_reg = -1; unsigned n=0; for( r=regs.begin(); r!=regs.end();r++,n++ ) { unsigned reg = *r; - unsigned bank = register_bank(reg,warp.warp_id(),m_num_banks,m_bank_warp_shift); + unsigned bank = register_bank(reg,inst.warp_id(),m_num_banks,m_bank_warp_shift); if( m_arbiter.bank_idle(bank) ) { - m_arbiter.allocate_bank_for_write(bank,op_t(&warp,reg,m_num_banks,m_bank_warp_shift)); + m_arbiter.allocate_bank_for_write(bank,op_t(&inst,reg,m_num_banks,m_bank_warp_shift)); } else { return false; } - last_reg=reg; } return true; } @@ -2237,13 +2370,6 @@ void opndcoll_rfu_t::allocate_reads() } } - -void gpgpu_sim::decrement_atomic_count( unsigned sid, unsigned wid ) -{ - m_sc[sid]->decrement_atomic_count(wid); -} - - bool opndcoll_rfu_t::collector_unit_t::ready() const { return (!m_free) && m_not_ready.none() && (*m_port)->empty(); @@ -2320,3 +2446,159 @@ class ptx_thread_info *shader_core_ctx::get_thread_state( unsigned hw_thread_id assert( hw_thread_id < m_config->n_thread_per_shader ); return m_thread[ hw_thread_id ].m_functional_model_thread_state; } + +simt_core_cluster::simt_core_cluster( class gpgpu_sim *gpu, + unsigned cluster_id, + struct shader_core_config *config, + struct shader_core_stats *stats ) +{ + m_cta_issue_next_core=0; + m_cluster_id=cluster_id; + m_gpu = gpu; + m_config = config; + m_stats = stats; + m_core = new shader_core_ctx*[ config->n_simt_cores_per_cluster ]; + for( unsigned i=0; i < config->n_simt_cores_per_cluster; i++ ) + m_core[i] = new shader_core_ctx(gpu,this,cid_to_sid(i),m_cluster_id,config,stats); +} + +void simt_core_cluster::core_cycle() +{ + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + m_core[i]->cycle(); +} + +void simt_core_cluster::reinit() +{ + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + m_core[i]->reinit(0,m_config->n_thread_per_shader,true); +} + +unsigned simt_core_cluster::max_cta( class function_info *kernel ) +{ + return m_config->n_simt_cores_per_cluster * m_core[0]->max_cta(kernel); +} + +int simt_core_cluster::get_not_completed() const +{ + unsigned not_completed=0; + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + not_completed += m_core[i]->get_not_completed(); + return not_completed; +} + +unsigned simt_core_cluster::get_n_active_cta() const +{ + unsigned n=0; + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + n += m_core[i]->get_n_active_cta(); + return n; +} + +void simt_core_cluster::issue_block2core( class kernel_info_t &kernel ) +{ + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) { + unsigned core = (i+m_cta_issue_next_core)%m_config->n_simt_cores_per_cluster; + if( m_core[core]->get_n_active_cta() < m_core[core]->max_cta(kernel.entry()) ) { + m_core[core]->issue_block2core(kernel); + break; + } + } +} + +void simt_core_cluster::cache_flush() +{ + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + m_core[i]->cache_flush(); +} + +bool simt_core_cluster::icnt_injection_buffer_full(new_addr_type addr, int bsize, bool write ) +{ + //requests should be single always now + int rsize = bsize; + //maintain similar functionality with fq_push, if its a read, bsize is the load size, not the request's size + if (!write) + rsize = READ_PACKET_SIZE; + return ! ::icnt_has_buffer(m_cluster_id, rsize); +} + +void simt_core_cluster::icnt_inject_request_packet(class mem_fetch *mf) +{ + // stats + if (mf->get_is_write()) m_stats->made_write_mfs++; + else m_stats->made_read_mfs++; + switch (mf->get_mem_acc()) { + case CONST_ACC_R: m_stats->gpgpu_n_mem_const++; break; + case TEXTURE_ACC_R: m_stats->gpgpu_n_mem_texture++; break; + case GLOBAL_ACC_R: m_stats->gpgpu_n_mem_read_global++; break; + case GLOBAL_ACC_W: m_stats->gpgpu_n_mem_write_global++; break; + case LOCAL_ACC_R: m_stats->gpgpu_n_mem_read_local++; break; + case LOCAL_ACC_W: m_stats->gpgpu_n_mem_write_local++; break; + case INST_ACC_R: m_stats->gpgpu_n_mem_read_inst++; break; + default: assert(0); + } + + unsigned destination = mf->get_tlx_addr().chip; + mf->set_status(IN_ICNT2MEM,MR_ICNT_PUSHED,gpu_sim_cycle+gpu_tot_sim_cycle); + if (!mf->get_is_write()) { + mf->set_type(RD_REQ); + ::icnt_push(m_cluster_id, m_config->mem2device(destination), (void*)mf, mf->get_ctrl_size() ); + } else { + mf->set_type(WT_REQ); + ::icnt_push(m_cluster_id, m_config->mem2device(destination), (void*)mf, mf->size()); + //gpgpu_n_sent_writes++; + } +} + +void simt_core_cluster::icnt_eject_response_packet(class mem_fetch * mf) +{ + assert( mf->get_tpc() == m_cluster_id ); + m_response_fifo.push_back(mf); +} + +void simt_core_cluster::icnt_cycle() +{ + if( !m_response_fifo.empty() ) { + mem_fetch *mf = m_response_fifo.front(); + unsigned cid = sid_to_cid(mf->get_sid()); + if( mf->get_mem_acc() == INST_ACC_R ) { + // instruction fetch response + if( !m_core[cid]->fetch_unit_response_buffer_full() ) { + m_response_fifo.pop_front(); + m_core[cid]->accept_fetch_response(mf); + } + } else { + // data response + if( !m_core[cid]->ldst_unit_response_buffer_full() ) { + m_response_fifo.pop_front(); + m_core[cid]->accept_ldst_unit_response(mf); + } + } + } + if( m_response_fifo.size() < m_config->n_simt_ejection_buffer_size ) { + mem_fetch *mf = (mem_fetch*) ::icnt_pop(m_cluster_id); + if (!mf) + return; + assert(mf->get_tpc() == m_cluster_id); + assert(mf->get_type() == REPLY_DATA); + mf->set_status(IN_CLUSTER2SHADER,MR_2SH_FQ_POP,gpu_sim_cycle+gpu_tot_sim_cycle); + //m_memory_stats->memlatstat_read_done(mf,m_shader_config->max_warps_per_shader); + m_response_fifo.push_back(mf); + } +} + +void simt_core_cluster::mem_instruction_stats(class warp_inst_t &inst) +{ + m_gpu->mem_instruction_stats(inst); +} + +void simt_core_cluster::get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ) +{ + unsigned cid = 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[sid_to_cid(sid)]->display_pipeline(fout,print_mem,mask); +} diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index d6ef552..b516495 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -171,7 +171,7 @@ public: unsigned get_n_atomic() const { return m_n_atomic; } void inc_n_atomic() { m_n_atomic++; } - void dec_n_atomic() { m_n_atomic--; } + void dec_n_atomic(unsigned n) { m_n_atomic-=n; } void set_membar() { m_membar=true; } void clear_membar() { m_membar=false; } @@ -209,16 +209,11 @@ public: m_ibuffer[m_next].m_inst = NULL; m_ibuffer[m_next].m_valid = false; } - void ibuffer_step() - { - m_next = (m_next+1)%IBUFFER_SIZE; - } - bool imiss_pending() const { return m_imiss_pending!=NULL; } - void set_imiss_pending( class mshr_entry *mshr ) - { - m_imiss_pending=mshr; - } - void clear_imiss_pending() { m_imiss_pending=NULL; } + void ibuffer_step() { m_next = (m_next+1)%IBUFFER_SIZE; } + + bool imiss_pending() const { return m_imiss_pending; } + void set_imiss_pending() { m_imiss_pending=true; } + void clear_imiss_pending() { m_imiss_pending=false; } bool stores_done() const { return m_stores_outstanding == 0; } void inc_store_req() { m_stores_outstanding++; } @@ -229,13 +224,13 @@ public: } bool inst_in_pipeline() const { return m_inst_in_pipeline > 0; } - void inc_inst_in_pipeline() { m_inst_in_pipeline++; } void dec_inst_in_pipeline() { assert( m_inst_in_pipeline > 0 ); m_inst_in_pipeline--; } + unsigned get_cta_id() const { return m_cta_id; } private: @@ -248,7 +243,7 @@ private: address_type m_next_pc; unsigned n_completed; // number of threads in warp completed - class mshr_entry *m_imiss_pending; + bool m_imiss_pending; struct ibuffer_entry { ibuffer_entry() { m_valid = false; m_inst = NULL; } @@ -308,34 +303,40 @@ class mshr_entry { public: mshr_entry() { - m_status = INVALID; m_merged_requests=NULL; m_mf=NULL; m_id=0; + m_status = INITIALIZED; + m_isatomic=false; } void set_id( unsigned n ) { m_id = n; } + unsigned get_id() const { return m_id; } void init( new_addr_type address, bool wr, memory_space_t space, unsigned warp_id ); void clear() { m_insts.clear(); } void set_mf( class mem_fetch *mf ) { m_mf=mf; } class mem_fetch *get_mf() { return m_mf; } - void add_inst( warp_inst_t inst ) { m_insts.push_back(inst); } - void set_status( enum mshr_status status ); + void add_inst( warp_inst_t inst ) + { + m_insts.push_back(inst); + m_isatomic = inst.isatomic(); + } void merge( mshr_entry *mshr ) { //merge this request; m_merged_requests = mshr; mshr->m_merged_on_other_reqest = true; } - void do_atomic() + void set_fetched() { - for( std::vector<warp_inst_t>::iterator e=m_insts.begin(); e != m_insts.end(); ++e ) { - warp_inst_t &inst = *e; - inst.do_atomic(); + mshr_entry *mshr = this; + while( mshr ) { + mshr->m_status=FETCHED; + mshr->m_mf=NULL; + mshr=mshr->m_merged_requests; } } mshr_entry *get_last_merged() { - assert(m_status!=INVALID); mshr_entry *mshr_hit = this; while (mshr_hit->m_merged_requests) mshr_hit = mshr_hit->m_merged_requests; @@ -357,7 +358,7 @@ public: unsigned get_warp_id() const { return m_warp_id; } bool ismerged() const { return m_merged_on_other_reqest; } - bool fetched() const { return m_status == FETCHED;}; + bool fetched() const { return m_status==FETCHED;} bool iswrite() const { return m_iswrite; } bool isinst() const { return m_isinst; } bool istexture() const { return m_istexture; } @@ -367,17 +368,10 @@ public: unsigned num_inst() const { return m_insts.size(); } inst_t &get_inst(unsigned n) { - assert(m_status!=INVALID&&m_insts.size()>0); + assert(n<m_insts.size()); return m_insts[n]; } - bool isatomic() const - { - assert(m_status!=INVALID); - if( isinst() ) - return false; - assert(m_insts.size()>0); - return m_insts[0].isatomic(); - } + bool isatomic() const { return m_isatomic; } new_addr_type get_addr() const { return m_addr; } void print(FILE *fp) const; @@ -390,13 +384,14 @@ private: bool m_iswrite; bool m_merged_on_other_reqest; //true if waiting for another mshr - this mshr doesn't send a memory request struct mshr_entry *m_merged_requests; //mshrs waiting on this mshr - enum mshr_status m_status; class mem_fetch *m_mf; // link to corresponding memory fetch structure + enum mshr_status m_status; bool m_isinst; //if it's a request from the instruction cache bool m_istexture; //if it's a request from the texture cache bool m_isconst; //if it's a request from the constant cache bool m_islocal; //if it's a request to the local memory of a thread bool m_wt_no_w2cache; //in write_through, sometimes need to prevent writing back returning data into cache, because its been written in the meantime. + bool m_isatomic; }; const unsigned WARP_PER_CTA_MAX = 32; @@ -822,7 +817,7 @@ public: void pop_return_head(); mshr_entry* add_mshr(mem_access_t &access, warp_inst_t* inst); - void mshr_return_from_mem(mshr_entry *mshr); + void mshr_return_from_mem(unsigned mshr_id); unsigned get_max_mshr_used() const {return m_max_mshr_used;} void print(FILE* fp); @@ -872,9 +867,8 @@ struct ifetch_buffer_t { class simd_function_unit { public: - simd_function_unit( warp_inst_t **result_port, const shader_core_config *config ) + simd_function_unit( const shader_core_config *config ) { - m_result_port = result_port; m_config=config; m_dispatch_reg = new warp_inst_t(config); } @@ -895,14 +889,13 @@ public: protected: std::string m_name; const shader_core_config *m_config; - warp_inst_t **m_result_port; warp_inst_t *m_dispatch_reg; }; -class alu : public simd_function_unit { +class pipelined_simd_unit : public simd_function_unit { public: - alu( warp_inst_t **result_port, const shader_core_config *config, unsigned max_latency ) - : simd_function_unit(result_port,config) + pipelined_simd_unit( warp_inst_t **result_port, const shader_core_config *config, unsigned max_latency ) + : simd_function_unit(config) { m_result_port = result_port; m_pipeline_depth = max_latency; @@ -946,16 +939,17 @@ public: } } } -private: +protected: unsigned m_pipeline_depth; warp_inst_t **m_pipeline_reg; + warp_inst_t **m_result_port; }; -class sfu : public alu +class sfu : public pipelined_simd_unit { public: sfu( warp_inst_t **result_port, const shader_core_config *config ) - : alu(result_port,config,config->max_sfu_latency) { m_name = "SFU"; } + : pipelined_simd_unit(result_port,config,config->max_sfu_latency) { m_name = "SFU"; } virtual bool can_issue( const warp_inst_t &inst ) const { switch(inst.op) { @@ -963,15 +957,15 @@ public: case ALU_SFU_OP: break; default: return false; } - return alu::can_issue(inst); + return pipelined_simd_unit::can_issue(inst); } }; -class sp_unit : public alu +class sp_unit : public pipelined_simd_unit { public: sp_unit( warp_inst_t **result_port, const shader_core_config *config ) - : alu(result_port,config,config->max_sp_latency) { m_name = "SP "; } + : pipelined_simd_unit(result_port,config,config->max_sp_latency) { m_name = "SP "; } virtual bool can_issue( const warp_inst_t &inst ) const { switch(inst.op) { @@ -981,15 +975,18 @@ public: case MEMORY_BARRIER_OP: return false; default: break; } - return alu::can_issue(inst); + return pipelined_simd_unit::can_issue(inst); } }; -class ldst_unit : public simd_function_unit { +class simt_core_cluster; + +class ldst_unit: public pipelined_simd_unit { public: - ldst_unit( gpgpu_sim *gpu, + ldst_unit( simt_core_cluster *gpu, shader_core_ctx *core, - warp_inst_t **result_port, + opndcoll_rfu_t *operand_collector, + Scoreboard *scoreboard, shader_core_config *config, shader_core_stats *stats, unsigned sid, unsigned tpc ); @@ -998,6 +995,7 @@ public: virtual void cycle(); void fill( mem_fetch *mf ); void flush(); + void writeback(); // accessors virtual bool can_issue( const warp_inst_t &inst ) const @@ -1011,6 +1009,7 @@ public: return simd_function_unit::can_issue(inst); } virtual bool stallable() const { return true; } + bool response_buffer_full() const; void print(FILE *fout) const; private: @@ -1035,8 +1034,8 @@ private: warp_inst_t &inst ); mem_stage_stall_type send_mem_request(warp_inst_t &inst, mem_access_t &access); - gpgpu_sim *m_gpu; - shader_core_ctx *m_core; + class simt_core_cluster *m_cluster; + class shader_core_ctx *m_core; unsigned m_sid; unsigned m_tpc; @@ -1044,6 +1043,10 @@ private: cache_t *m_L1T; // texture cache cache_t *m_L1C; // constant cache mshr_shader_unit *m_mshr_unit; + std::map<unsigned/*warp_id*/, std::map<unsigned/*regnum*/,unsigned/*count*/> > m_pending_writes; + std::list<mem_fetch*> m_response_fifo; + opndcoll_rfu_t *m_operand_collector; + Scoreboard *m_scoreboard; enum mem_stage_stall_type m_mem_rc; @@ -1065,7 +1068,7 @@ class shader_core_ctx : public core_t { public: shader_core_ctx( class gpgpu_sim *gpu, - const char *name, + class simt_core_cluster *cluster, unsigned shader_id, unsigned tpc_id, struct shader_core_config *config, @@ -1085,7 +1088,7 @@ public: bool warp_waiting_at_mem_barrier( unsigned warp_id ); void allocate_barrier( unsigned cta_id, warp_set_t warps ); void deallocate_barrier( unsigned cta_id ); - void decrement_atomic_count( unsigned wid ); + void decrement_atomic_count( unsigned wid, unsigned n ); void cycle(); @@ -1097,10 +1100,12 @@ public: void display_pdom_state(FILE *fout, int mask ); void display_pipeline( FILE *fout, int print_mem, int mask3bit ); void register_cta_thread_exit(int cta_num ); - void fill_shd_L1_with_new_line( class mem_fetch * mf ); + bool fetch_unit_response_buffer_full() const; + void accept_fetch_response( mem_fetch *mf ); + bool ldst_unit_response_buffer_full(); + void accept_ldst_unit_response( class mem_fetch * mf ); void store_ack( class mem_fetch *mf ); void dump_istream_state( FILE *fout ); - unsigned first_valid_thread( unsigned stage ); class ptx_thread_info* get_functional_thread( unsigned tid ) { return m_thread[tid].m_functional_model_thread_state; } std::list<unsigned> get_regs_written( const inst_t &fvt ) const; const shader_core_config *get_config() const { return m_config; } @@ -1114,11 +1119,10 @@ public: unsigned get_thread_n_l1_access_ac( unsigned tid ) const { return m_thread[tid].n_l1_access_ac; } unsigned get_n_active_cta() const { return m_n_active_cta; } void inc_store_req( unsigned warp_id) { m_warp[warp_id].inc_store_req(); } + void dec_inst_in_pipeline( unsigned warp_id ) { m_warp[warp_id].dec_inst_in_pipeline(); } private: - void clear_stage_reg(int stage); - address_type next_pc( int tid ) const; void fetch(); @@ -1132,15 +1136,13 @@ private: void writeback(); - void call_thread_done(inst_t &done_inst ); - void print_stage(unsigned int stage, FILE *fout) const; // general information unsigned m_sid; // shader id unsigned m_tpc; // texture processor cluster id (aka, node id when using interconnect concentration) - const char *m_name; const shader_core_config *m_config; + class simt_core_cluster *m_cluster; class gpgpu_sim *m_gpu; // statistics @@ -1180,4 +1182,46 @@ private: std::bitset<MAX_ALU_LATENCY> m_result_bus; }; +class simt_core_cluster { +public: + simt_core_cluster( class gpgpu_sim *gpu, + unsigned cluster_id, + struct shader_core_config *config, + struct shader_core_stats *stats ); + + void core_cycle(); + void icnt_cycle(); + + void reinit(); + unsigned max_cta( class function_info *kernel ); + int get_not_completed() const; + unsigned get_n_active_cta() const; + void issue_block2core( class kernel_info_t &kernel ); + void cache_flush(); + + bool icnt_injection_buffer_full(new_addr_type addr, int bsize, bool write ); + void icnt_inject_request_packet(class mem_fetch *mf); + bool icnt_ejection_buffer_full() const { return m_response_fifo.size() >= m_config->n_simt_ejection_buffer_size; } + void icnt_eject_response_packet(class mem_fetch * mf); + void mem_instruction_stats(class warp_inst_t &inst); + void get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ); + + gpgpu_sim *get_gpu() { return m_gpu; } + + void display_pipeline( unsigned sid, FILE *fout, int print_mem, int mask ); + +private: + unsigned sid_to_cid( unsigned sid ) { return sid % m_config->n_simt_cores_per_cluster; } + unsigned cid_to_sid( unsigned cid ) { return m_cluster_id*m_config->n_simt_cores_per_cluster + cid; } + + unsigned m_cluster_id; + gpgpu_sim *m_gpu; + const shader_core_config *m_config; + shader_core_stats *m_stats; + shader_core_ctx **m_core; + + unsigned m_cta_issue_next_core; + std::list<mem_fetch*> m_response_fifo; +}; + #endif /* SHADER_H */ diff --git a/src/gpgpu-sim/stats.h b/src/gpgpu-sim/stats.h index 2c494eb..20acfa1 100644 --- a/src/gpgpu-sim/stats.h +++ b/src/gpgpu-sim/stats.h @@ -120,7 +120,6 @@ struct shader_core_stats unsigned int gpu_stall_by_MSHRwb; unsigned int gpu_stall_shd_mem; unsigned int gpu_stall_sh2icnt; - unsigned int *max_return_queue_length; //memory access classification int gpgpu_n_mem_read_local; diff --git a/src/gpgpu-sim/visualizer.cc b/src/gpgpu-sim/visualizer.cc index 4474dcd..15dc157 100644 --- a/src/gpgpu-sim/visualizer.cc +++ b/src/gpgpu-sim/visualizer.cc @@ -126,6 +126,7 @@ void gpgpu_sim::visualizer_printstat() gzsetparams(visualizer_file, g_visualizer_zlevel, Z_DEFAULT_STRATEGY); visualizer_first_printstat = false; + /* // instruction count per shader core gzprintf(visualizer_file, "shaderinsncount: "); for (unsigned i=0;i<m_n_shader;i++) @@ -137,6 +138,7 @@ void gpgpu_sim::visualizer_printstat() for (unsigned i=0;i<m_n_shader;i++) gzprintf(visualizer_file, "%u ", m_sc[i]->get_n_diverge()); gzprintf(visualizer_file, "\n"); + */ cflog_visualizer_gzprint(visualizer_file); shader_CTA_count_visualizer_gzprint(visualizer_file); @@ -172,7 +174,7 @@ void gpgpu_sim::visualizer_printstat() m_sc[i]->new_cache_window(); */ - for (unsigned i=0;i<m_n_mem;i++) + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) m_memory_partition_unit[i]->visualizer_print(visualizer_file); // overall cache miss rates @@ -208,7 +210,7 @@ void gpgpu_sim::visualizer_printstat() time_vector_print_interval2gzfile(visualizer_file); gzprintf(visualizer_file, "WarpDivergenceBreakdown:"); unsigned int total=0; - unsigned int cf = (m_shader_config->gpgpu_warpdistro_shader==-1)?m_n_shader:1; + unsigned int cf = (m_shader_config->gpgpu_warpdistro_shader==-1)?num_shader():1; gzprintf(visualizer_file, " %d", (m_shader_stats->shader_cycle_distro[0] - last_shader_cycle_distro[0]) / cf ); gzprintf(visualizer_file, " %d", (m_shader_stats->shader_cycle_distro[2] - last_shader_cycle_distro[2]) / cf ); for (unsigned i=0; i<m_shader_config->warp_size+3; i++) { diff --git a/src/gpgpusim_entrypoint.cc b/src/gpgpusim_entrypoint.cc index 6f13cd2..f6dea90 100644 --- a/src/gpgpusim_entrypoint.cc +++ b/src/gpgpusim_entrypoint.cc @@ -95,9 +95,7 @@ void *gpgpu_sim_thread(void*) { do { sem_wait(&g_sim_signal_start); - unsigned grid; - class function_info *entry; - g_the_gpu.next_grid(grid,entry); + g_the_gpu.next_grid(); g_the_gpu.run_gpu_sim(); print_simulation_time(); sem_post(&g_sim_signal_finish); diff --git a/src/intersim/interconnect_interface.cpp b/src/intersim/interconnect_interface.cpp index 0ed7150..5d3d55c 100644 --- a/src/intersim/interconnect_interface.cpp +++ b/src/intersim/interconnect_interface.cpp @@ -67,6 +67,18 @@ public: } return data; } + void * top_packet(){ + assert (packet_n); + void * data = NULL; + void * temp_d = buf.front(); + while (data==NULL) { + if (tail_flag.front()) { + data = buf.front(); + } + assert(temp_d == buf.front()); //all flits must belong to the same packet + } + return data; + } void push_flit_data(void* data,bool is_tail) { buf.push(data); tail_flag.push(is_tail); @@ -130,17 +142,19 @@ void map_gen(int dim,int memcount, int memnodes[]) assert(k==dim*dim); } -void display_map(int dim,int count){ +void display_map(int dim,int count) +{ + printf("GPGPU-Sim uArch: "); int i=0; for (i=0;i<count;i++) { - printf("%d ",node_map[i]); - if (i%dim ==0) { - printf("\n"); - } + printf("%3d ",node_map[i]); + if (i%dim ==0) + printf("\nGPGPU-Sim uArch: "); } } -void create_node_map(int n_shader, int n_mem, int size, int use_map) { +void create_node_map(int n_shader, int n_mem, int size, int use_map) +{ node_map = (int*)malloc((size)*sizeof(int)); if (use_map) { switch (size) { @@ -216,7 +230,7 @@ void create_node_map(int n_shader, int n_mem, int size, int use_map) { } } } - printf("nodemap\n"); + printf("GPGPU-Sim uArch: interconnect nodemap\n"); display_map((int) sqrt(size),size); } @@ -287,18 +301,18 @@ void icnt_init_grid (){ } } -int interconnect_has_buffer(unsigned int input_node, unsigned int tot_req_size) +bool interconnect_has_buffer(unsigned int input_node, unsigned int tot_req_size) { unsigned int input = node_map[input_node]; - int has_buffer; + bool has_buffer = false; unsigned int n_flits = tot_req_size / _flit_size + ((tot_req_size % _flit_size)? 1:0); if (!(fixed_lat_icnt || perfect_icnt)) { has_buffer = (traffic[0]->_partial_packets[input][0].size() + n_flits) <= input_buffer_capacity; if ((net_c>1) && is_mem(input)) has_buffer = (traffic[1]->_partial_packets[input][0].size() + n_flits) <= input_buffer_capacity; } else { - has_buffer = 1; + has_buffer = true; } return has_buffer; } @@ -554,6 +568,7 @@ void time_vector_update(unsigned int uid, int slot , long int cycle, int type); void time_vector_update_icnt_injected(void* data, int input) { + /* mem_fetch* mf = (mem_fetch*) data; if( mf->get_mshr() && !mf->get_mshr()->isinst() ) { unsigned uid=mf->get_request_uid(); @@ -565,4 +580,5 @@ void time_vector_update_icnt_injected(void* data, int input) time_vector_update( uid, MR_ICNT_INJECTED, cycle,req_type ); } } + */ } diff --git a/src/intersim/interconnect_interface.h b/src/intersim/interconnect_interface.h index 3e3826d..9003fc6 100644 --- a/src/intersim/interconnect_interface.h +++ b/src/intersim/interconnect_interface.h @@ -13,7 +13,7 @@ struct glue_buf { }; //node side functions -int interconnect_has_buffer(unsigned int input, unsigned int size); +bool interconnect_has_buffer(unsigned int input, unsigned int size); void interconnect_push ( unsigned int input, unsigned int output, void* data, unsigned int size); void* interconnect_pop(unsigned int output); |
