diff options
Diffstat (limited to 'src/gpgpu-sim/gpu-sim.cc')
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.cc | 1583 |
1 files changed, 693 insertions, 890 deletions
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index b5527e1..8114b9e 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -91,18 +91,19 @@ #include "../cuda-sim/ptx-stats.h" #include "../intersim/statwraper.h" +#include "../intersim/interconnect_interface.h" #include "../abstract_hardware_model.h" #include "../debug.h" #include "../gpgpusim_entrypoint.h" #include "../cuda-sim/cuda-sim.h" #include "mem_latency_stat.h" +#include "visualizer.h" +#include "stats.h" #include <stdio.h> #include <string.h> -#include <queue> - #define MAX(a,b) (((a)>(b))?(a):(b)) bool g_interactive_debugger_enabled=false; @@ -115,13 +116,10 @@ unsigned freed_L2write_mfs = 0; unsigned freed_dummy_read_mfs = 0; unsigned long long gpu_sim_cycle = 0; unsigned long long gpu_sim_insn = 0; -unsigned long long gpu_sim_insn_no_ld_const = 0; unsigned long long gpu_sim_prev_insn = 0; -unsigned long long gpu_sim_insn_last_update = 0; unsigned long long gpu_tot_sim_cycle = 0; unsigned long long gpu_tot_sim_insn = 0; unsigned long long gpu_last_sim_cycle = 0; -unsigned long long gpu_completed_thread = 0; unsigned long long gpu_tot_issued_cta = 0; unsigned long long gpu_tot_completed_thread = 0; @@ -130,27 +128,17 @@ unsigned int **num_activates; //num_activates[dram chip id][bank id] unsigned int **row_access; //row_access[dram chip id][bank id] unsigned int **max_conc_access2samerow; //max_conc_access2samerow[dram chip id][bank id] unsigned int **max_servicetime2samerow; //max_servicetime2samerow[dram chip id][bank id] -unsigned int L1_read_miss = 0; -unsigned int L1_write_miss = 0; -unsigned int L1_write_hit_on_miss = 0; -unsigned int L1_writeback = 0; -unsigned int L1_texture_miss = 0; -unsigned int L1_const_miss = 0; unsigned int gpgpu_n_sent_writes = 0; unsigned int gpgpu_n_processed_writes = 0; -unsigned int *max_return_queue_length; // performance counter for stalls due to congestion. -unsigned int gpu_stall_shd_mem = 0; unsigned int gpu_stall_wr_back = 0; unsigned int gpu_stall_dramfull = 0; unsigned int gpu_stall_icnt2sh = 0; -unsigned int gpu_stall_by_MSHRwb = 0; //shader cannot send to icnt because icnt buffer is full //Note: it is accumulative for all shaders and is never reset //so it might increase 8 times in a cycle if we have 8 shaders -unsigned int gpu_stall_sh2icnt = 0; char *gpgpu_runtime_stat; int gpu_stat_sample_freq = 10000; int gpu_runtime_stat_flag = 0; @@ -160,7 +148,6 @@ unsigned long long gpu_max_insn = 0; int gpu_deadlock = 0; unsigned g_next_mf_request_uid = 1; static unsigned long long last_gpu_sim_insn = 0; -int g_nthreads_issued; int g_total_cta_left; // GPGPU-Sim timing model options @@ -168,34 +155,12 @@ int gpu_max_cycle_opt; int gpu_max_insn_opt; int gpu_max_cta_opt; bool gpu_deadlock_detect; -int gpgpu_simd_model; -enum dram_ctrl_t gpgpu_dram_scheduler; -bool gpgpu_no_dl1; -char *gpgpu_cache_texl1_opt; -char *gpgpu_cache_constl1_opt; -char *gpgpu_cache_dl1_opt; -char *gpgpu_cache_dl2_opt; -int gpgpu_partial_write_mask; -bool gpgpu_perfect_mem; char *gpgpu_shader_core_pipeline_opt; -unsigned int gpgpu_dram_buswidth; -unsigned int gpgpu_dram_burst_length; int gpgpu_dram_sched_queue_size; -char *gpgpu_dram_timing_opt; bool gpgpu_flush_cache; int gpgpu_mem_address_mask; int gpgpu_cflog_interval; -void ptx_dump_regs( void *thd ); -unsigned ptx_kernel_program_size(); -void visualizer_printstat(); -void time_vector_create(int ld_size,int st_size); -void time_vector_print(void); -void time_vector_update(unsigned int uid,int slot ,long int cycle,int type); -void node_req_hist_clear(void *p); -void node_req_hist_dump(void *p); -void node_req_hist_update(void * p,int node, long long cycle); - /* Defining Clock Domains basically just the ratio is important */ @@ -204,114 +169,34 @@ basically just the ratio is important */ #define DRAM 0x04 #define ICNT 0x08 -double core_time=0; -double icnt_time=0; -double dram_time=0; -double l2_time=0; - -double core_freq=2 MhZ; -double icnt_freq=2 MhZ; -double dram_freq=2 MhZ; -double l2_freq=2 MhZ; - -double core_period = 1 /( 2 MhZ); -double icnt_period = 1 /( 2 MhZ); -double dram_period = 1 /( 2 MhZ); -double l2_period = 1 / (2 MhZ); char * gpgpu_clock_domains; /* GPU uArch parameters */ -unsigned int gpu_n_mem; -unsigned int gpu_mem_n_bk; unsigned int gpu_n_mem_per_ctrlr; -unsigned int gpu_n_shader; -int gpu_concentration; int gpu_n_tpc; -unsigned int gpu_n_mshr_per_shader; -unsigned int gpu_n_thread_per_shader; -unsigned int gpu_n_warp_per_shader; -unsigned int gpu_n_mshr_per_thread = 1; -bool gpgpu_reg_bankconflict; -bool gpgpu_operand_collector; -int gpgpu_operand_collector_num_units; -int gpgpu_operand_collector_num_units_sfu; -unsigned int gpgpu_pre_mem_stages; -bool gpgpu_no_divg_load; char *gpgpu_dwf_hw_opt; bool gpgpu_thread_swizzling; -bool gpgpu_strict_simd_wrbk; -int pdom_sched_type; -int n_pdom_sc_orig_stat = 0; //the selected pdom schedular is used -int n_pdom_sc_single_stat = 0; //only a single warp is ready to go in that cycle. -int *num_warps_issuable; -int *num_warps_issuable_pershader; -bool gpgpu_cuda_sim; -bool gpgpu_spread_blocks_across_cores; -bool gpgpu_stall_on_use; -shader_core_ctx_t **sc; -dram_t **dram; -unsigned int common_clock = 0; unsigned int more_thread = 1; -unsigned int warp_conflict_at_writeback = 0; -unsigned int gpgpu_commit_pc_beyond_two = 0; -bool gpgpu_cache_wt_through; - -//memory access classification -int gpgpu_n_mem_read_local = 0; -int gpgpu_n_mem_write_local = 0; -int gpgpu_n_mem_texture = 0; -int gpgpu_n_mem_const = 0; -int gpgpu_n_mem_read_global = 0; -int gpgpu_n_mem_write_global = 0; #define MEM_LATENCY_STAT_IMPL #include "mem_latency_stat.h" -unsigned char fq_has_buffer(unsigned long long int addr, int bsize, bool write, int sid ); -unsigned char fq_push(unsigned long long int addr, int bsize, unsigned char write, partial_write_mask_t partial_write_mask, - int sid, int wid, mshr_entry* mshr, int cache_hits_waiting, - enum mem_access_type mem_acc, address_type pc); -int issue_mf_from_fq(mem_fetch_t *mf); -unsigned char single_check_icnt_has_buffer(int chip, int sid, unsigned char is_write ); -unsigned char fq_pop(int tpc_id); -void fill_shd_L1_with_new_line(shader_core_ctx_t * sc, mem_fetch_t * mf); - -void set_param_gpgpu_num_shaders(int num_shaders); -unsigned ptx_sim_grid_size(); -void icnt_init_grid(); -void interconnect_stats(); -void icnt_overal_stat(); -void gpu_sim_loop( int grid_num ); -void print_shader_cycle_distro( FILE *fout ) ; -void find_reconvergence_points(); -void dwf_process_reconv_pts(); - int g_ptx_inst_debug_to_file; char* g_ptx_inst_debug_file; int g_ptx_inst_debug_thread_uid; -#define CREATELOG 111 -#define SAMPLELOG 222 -#define DUMPLOG 333 -void L2c_log(int task); -void dram_log(int task); - -// DRAM delay queue and memory_fetch container -// A delay queue for each mem - vector of queues -struct dram_delay_t{ - unsigned long long ready_cycle; - mem_fetch_t* mf; -}; -std::vector< std::queue<dram_delay_t> > dram_delay_queues; +int g_ptx_convert_to_ptxplus; +int g_ptx_save_converted_ptxplus; void visualizer_options(option_parser_t opp); -void gpu_reg_options(option_parser_t opp) + +void gpgpu_sim::reg_options(option_parser_t opp) { - option_parser_register(opp, "-gpgpu_simd_model", OPT_INT32, &gpgpu_simd_model, + option_parser_register(opp, "-gpgpu_simd_model", OPT_INT32, &m_shader_config->model, "0 = no recombination, 1 = post-dominator, 2 = MIMD, 3 = dynamic warp formation", "0"); - option_parser_register(opp, "-gpgpu_dram_scheduler", OPT_INT32, &gpgpu_dram_scheduler, - "0 = fifo (default), 1 = fast ideal", "0"); + option_parser_register(opp, "-gpgpu_dram_scheduler", OPT_INT32, &m_memory_config->scheduler_type, + "0 = fifo, 1 = FR-FCFS (defaul)", "1"); option_parser_register(opp, "-gpgpu_max_cycle", OPT_INT32, &gpu_max_cycle_opt, "terminates gpu simulation early (0 = no limit)", @@ -323,46 +208,54 @@ void gpu_reg_options(option_parser_t opp) "terminates gpu simulation early (0 = no limit)", "0"); - option_parser_register(opp, "-gpgpu_tex_cache:l1", OPT_CSTR, &gpgpu_cache_texl1_opt, + option_parser_register(opp, "-gpgpu_tex_cache:l1", OPT_CSTR, &m_shader_config->gpgpu_cache_texl1_opt, "per-shader L1 texture cache (READ-ONLY) config, i.e., {<nsets>:<linesize>:<assoc>:<repl>|none}", "512:64:2:L"); - option_parser_register(opp, "-gpgpu_const_cache:l1", OPT_CSTR, &gpgpu_cache_constl1_opt, + option_parser_register(opp, "-gpgpu_const_cache:l1", OPT_CSTR, &m_shader_config->gpgpu_cache_constl1_opt, "per-shader L1 constant memory cache (READ-ONLY) config, i.e., {<nsets>:<linesize>:<assoc>:<repl>|none}", "64:64:2:L"); - option_parser_register(opp, "-gpgpu_no_dl1", OPT_BOOL, &gpgpu_no_dl1, + option_parser_register(opp, "-gpgpu_no_dl1", OPT_BOOL, &m_shader_config->gpgpu_no_dl1, "no dl1 cache (voids -gpgpu_cache:dl1 option)", "0"); - option_parser_register(opp, "-gpgpu_cache:dl1", OPT_CSTR, &gpgpu_cache_dl1_opt, + option_parser_register(opp, "-gpgpu_cache:dl1", OPT_CSTR, &m_shader_config->gpgpu_cache_dl1_opt, "shader L1 data cache config, i.e., {<nsets>:<bsize>:<assoc>:<repl>|none}", "256:128:1:L"); - option_parser_register(opp, "-gpgpu_cache:dl2", OPT_CSTR, &gpgpu_cache_dl2_opt, + option_parser_register(opp, "-gpgpu_cache:il1", OPT_CSTR, &m_shader_config->gpgpu_cache_il1_opt, + "shader L1 instruction cache config, i.e., {<nsets>:<bsize>:<assoc>:<repl>|none}", + "4:256:4:L"); + + option_parser_register(opp, "-gpgpu_cache:dl2", OPT_CSTR, &m_memory_config->gpgpu_cache_dl2_opt, "unified banked L2 data cache config, i.e., {<nsets>:<bsize>:<assoc>:<repl>|none}; disabled by default", NULL); - option_parser_register(opp, "-gpgpu_perfect_mem", OPT_BOOL, &gpgpu_perfect_mem, + option_parser_register(opp, "-gpgpu_perfect_mem", OPT_BOOL, &m_shader_config->gpgpu_perfect_mem, "enable perfect memory mode (no cache miss)", "0"); + option_parser_register(opp, "-gpgpu_sm_uarch", OPT_CSTR, &m_shader_config->pipeline_model, + "shader core uarch model [GPGPUSIM_ORIG,GT200] (default=GPGPUSIM_ORIG)", + "GPGPUSIM_ORIG"); + option_parser_register(opp, "-gpgpu_shader_core_pipeline", OPT_CSTR, &gpgpu_shader_core_pipeline_opt, "shader core pipeline config, i.e., {<nthread>:<warpsize>:<pipe_simd_width>}", "256:32:32"); - option_parser_register(opp, "-gpgpu_shader_registers", OPT_UINT32, &gpgpu_shader_registers, + option_parser_register(opp, "-gpgpu_shader_registers", OPT_UINT32, &m_shader_config->gpgpu_shader_registers, "Number of registers per shader core. Limits number of concurrent CTAs. (default 8192)", "8192"); - option_parser_register(opp, "-gpgpu_shader_cta", OPT_UINT32, &gpgpu_shader_cta, + 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, &gpu_n_shader, + option_parser_register(opp, "-gpgpu_n_shader", OPT_UINT32, &m_n_shader, "number of shaders in gpu", "8"); - option_parser_register(opp, "-gpgpu_n_mem", OPT_UINT32, &gpu_n_mem, + option_parser_register(opp, "-gpgpu_n_mem", OPT_UINT32, &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, @@ -376,39 +269,39 @@ void gpu_reg_options(option_parser_t opp) "DWF scheduling heuristic: 0 = majority, 1 = minority, 2 = timestamp, 3 = pdom priority, 4 = pc-based, 5 = max-heap", "0"); - option_parser_register(opp, "-gpgpu_reg_bankconflict", OPT_BOOL, &gpgpu_reg_bankconflict, - "Check for bank conflict in the pipeline", + option_parser_register(opp, "-gpgpu_dwf_reg_bankconflict", OPT_BOOL, &m_shader_config->gpgpu_dwf_reg_bankconflict, + "bank conflict model used in MICRO'07/TACO'09 work (default=disabled)", "0"); option_parser_register(opp, "-gpgpu_dwf_regbk", OPT_BOOL, &gpgpu_dwf_regbk, "Have dwf scheduler to avoid bank conflict", "1"); - option_parser_register(opp, "-gpgpu_memlatency_stat", OPT_INT32, &gpgpu_memlatency_stat, + option_parser_register(opp, "-gpgpu_memlatency_stat", OPT_INT32, &m_memory_config->gpgpu_memlatency_stat, "track and display latency statistics 0x2 enables MC, 0x4 enables queue logs", "0"); - option_parser_register(opp, "-gpu_n_mshr_per_shader", OPT_UINT32, &gpu_n_mshr_per_shader, + option_parser_register(opp, "-gpu_n_mshr_per_shader", OPT_UINT32, &m_shader_config->n_mshr_per_shader, "Number of MSHRs per shader", "64"); - option_parser_register(opp, "-gpgpu_interwarp_mshr_merge", OPT_INT32, &gpgpu_interwarp_mshr_merge, + option_parser_register(opp, "-gpgpu_interwarp_mshr_merge", OPT_INT32, &m_shader_config->gpgpu_interwarp_mshr_merge, "interwarp coalescing", "0"); - option_parser_register(opp, "-gpgpu_dram_sched_queue_size", OPT_INT32, &gpgpu_dram_sched_queue_size, + option_parser_register(opp, "-gpgpu_dram_sched_queue_size", OPT_INT32, &m_memory_config->gpgpu_dram_sched_queue_size, "0 = unlimited (default); # entries per chip", "0"); - option_parser_register(opp, "-gpgpu_dram_buswidth", OPT_UINT32, &gpgpu_dram_buswidth, + option_parser_register(opp, "-gpgpu_dram_buswidth", OPT_UINT32, &m_memory_config->gpgpu_dram_buswidth, "default = 4 bytes (8 bytes per cycle at DDR)", "4"); - option_parser_register(opp, "-gpgpu_dram_burst_length", OPT_UINT32, &gpgpu_dram_burst_length, + option_parser_register(opp, "-gpgpu_dram_burst_length", OPT_UINT32, &m_memory_config->gpgpu_dram_burst_length, "Burst length of each DRAM request (default = 4 DDR cycle)", "4"); - option_parser_register(opp, "-gpgpu_dram_timing_opt", OPT_CSTR, &gpgpu_dram_timing_opt, + option_parser_register(opp, "-gpgpu_dram_timing_opt", OPT_CSTR, &m_memory_config->gpgpu_dram_timing_opt, "DRAM timing parameters = {nbk:tCCD:tRRD:tRCD:tRAS:tRP:tRC:CL:WL:tWTR}", "4:2:8:12:21:13:34:9:4:5"); @@ -421,13 +314,13 @@ void gpu_reg_options(option_parser_t opp) "Flush cache at the end of each kernel call", "0"); - option_parser_register(opp, "-gpgpu_pre_mem_stages", OPT_UINT32, &gpgpu_pre_mem_stages, + option_parser_register(opp, "-gpgpu_pre_mem_stages", OPT_UINT32, &m_shader_config->gpgpu_pre_mem_stages, "default = 0 pre-memory pipeline stages", "0"); - option_parser_register(opp, "-gpgpu_no_divg_load", OPT_BOOL, &gpgpu_no_divg_load, - "Don't allow divergence on load", - "0"); + option_parser_register(opp, "-gpgpu_no_divg_load", OPT_BOOL, &m_shader_config->gpgpu_no_divg_load, + "Don't allow divergence on load (meaningful for dynamic warp formation only)", + "1"); option_parser_register(opp, "-gpgpu_dwf_hw", OPT_CSTR, &gpgpu_dwf_hw_opt, "dynamic warp formation hw config, i.e., {<#LUT_entries>:<associativity>|none}", @@ -437,23 +330,15 @@ void gpu_reg_options(option_parser_t opp) "Thread Swizzling (1=on, 0=off)", "0"); - option_parser_register(opp, "-gpgpu_strict_simd_wrbk", OPT_BOOL, &gpgpu_strict_simd_wrbk, - "Applying Strick SIMD WriteBack Stage (1=on, 0=off)", - "0"); - - option_parser_register(opp, "-gpgpu_shmem_size", OPT_UINT32, &gpgpu_shmem_size, + option_parser_register(opp, "-gpgpu_shmem_size", OPT_UINT32, &m_shader_config->gpgpu_shmem_size, "Size of shared memory per shader core (default 16kB)", "16384"); - option_parser_register(opp, "-gpgpu_shmem_bkconflict", OPT_BOOL, &gpgpu_shmem_bkconflict, - "Turn on bank conflict check for shared memory", - "0"); - - option_parser_register(opp, "-gpgpu_shmem_pipe_speedup", OPT_INT32, &gpgpu_shmem_pipe_speedup, + option_parser_register(opp, "-gpgpu_shmem_pipe_speedup", OPT_INT32, &m_shader_config->gpgpu_shmem_pipe_speedup, "Number of groups each warp is divided for shared memory bank conflict check", "2"); - option_parser_register(opp, "-gpgpu_cache_wt_through", OPT_BOOL, &gpgpu_cache_wt_through, + option_parser_register(opp, "-gpgpu_cache_wt_through", OPT_BOOL, &m_shader_config->gpgpu_cache_wt_through, "L1 cache become write through (1=on, 0=off)", "0"); @@ -461,36 +346,24 @@ void gpu_reg_options(option_parser_t opp) "Stop the simulation at deadlock (1=on (default), 0=off)", "1"); - option_parser_register(opp, "-gpgpu_cache_bkconflict", OPT_BOOL, &gpgpu_cache_bkconflict, - "Turn on bank conflict check for L1 cache access", - "0"); - - option_parser_register(opp, "-gpgpu_n_cache_bank", OPT_INT32, &gpgpu_n_cache_bank, + option_parser_register(opp, "-gpgpu_n_cache_bank", OPT_INT32, &m_shader_config->gpgpu_n_cache_bank, "Number of banks in L1 cache, also for memory coalescing stall", "1"); - option_parser_register(opp, "-gpgpu_warpdistro_shader", OPT_INT32, &gpgpu_warpdistro_shader, + option_parser_register(opp, "-gpgpu_warpdistro_shader", OPT_INT32, &m_shader_config->gpgpu_warpdistro_shader, "Specify which shader core to collect the warp size distribution from", "-1"); - option_parser_register(opp, "-gpgpu_pdom_sched_type", OPT_INT32, &pdom_sched_type, + option_parser_register(opp, "-gpgpu_pdom_sched_type", OPT_INT32, &m_pdom_sched_type, "0 = first ready warp found, 1 = random, 8 = loose round robin", "8"); - option_parser_register(opp, "-gpgpu_spread_blocks_across_cores", OPT_BOOL, - &gpgpu_spread_blocks_across_cores, - "Spread block-issuing across all cores instead of filling up core by core (do NOT disable)", - "1"); - option_parser_register(opp, "-gpgpu_stall_on_use", OPT_BOOL, - &gpgpu_stall_on_use, + &m_shader_config->gpgpu_stall_on_use, "Enable stall-on-use", "1"); - option_parser_register(opp, "-gpgpu_cuda_sim", OPT_BOOL, &gpgpu_cuda_sim, - "use PTX instruction set", - "1"); option_parser_register(opp, "-gpgpu_ptx_instruction_classification", OPT_INT32, &gpgpu_ptx_instruction_classification, "if enabled will classify ptx instruction types per kernel (Max 255 kernels now)", @@ -502,34 +375,28 @@ void gpu_reg_options(option_parser_t opp) "Clock Domain Frequencies in MhZ {<Core Clock>:<ICNT Clock>:<L2 Clock>:<DRAM Clock>}", "500.0:2000.0:2000.0:2000.0"); - option_parser_register(opp, "-gpgpu_shmem_port_per_bank", OPT_INT32, &gpgpu_shmem_port_per_bank, + option_parser_register(opp, "-gpgpu_shmem_port_per_bank", OPT_INT32, &m_shader_config->gpgpu_shmem_port_per_bank, "Number of access processed by a shared memory bank per cycle (default = 2)", "2"); - option_parser_register(opp, "-gpgpu_cache_port_per_bank", OPT_INT32, &gpgpu_cache_port_per_bank, + option_parser_register(opp, "-gpgpu_cache_port_per_bank", OPT_INT32, &m_shader_config->gpgpu_cache_port_per_bank, "Number of access processed by a cache bank per cycle (default = 2)", "2"); - option_parser_register(opp, "-gpgpu_const_port_per_bank", OPT_INT32, &gpgpu_const_port_per_bank, + option_parser_register(opp, "-gpgpu_const_port_per_bank", OPT_INT32, &m_shader_config->gpgpu_const_port_per_bank, "Number of access processed by a constant cache bank per cycle (default = 2)", "2"); 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, "-gpgpu_partial_write_mask", OPT_INT32, &gpgpu_partial_write_mask, - "use partial write mask to filter memory requests <1>No extra reads(use this!)<2>extra reads generated for partial chunks", - "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_INT32, &gpgpu_local_mem_map, - "Mapping from local memory space address to simulated GPU physical address space (default = 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"); - option_parser_register(opp, "-gpgpu_reg_bank_conflict_model", OPT_BOOL, &gpgpu_reg_bank_conflict_model, - "Turn on register bank conflict model (default = off)", - "0"); - option_parser_register(opp, "-gpgpu_num_reg_banks", OPT_INT32, &gpgpu_num_reg_banks, + option_parser_register(opp, "-gpgpu_num_reg_banks", OPT_INT32, &m_shader_config->gpgpu_num_reg_banks, "Number of register banks (default = 8)", "8"); - option_parser_register(opp, "-gpgpu_reg_bank_use_warp_id", OPT_BOOL, &gpgpu_reg_bank_use_warp_id, + option_parser_register(opp, "-gpgpu_reg_bank_use_warp_id", OPT_BOOL, &m_shader_config->gpgpu_reg_bank_use_warp_id, "Use warp ID in mapping registers to banks (default = off)", "0"); option_parser_register(opp, "-gpgpu_ptx_inst_debug_to_file", OPT_BOOL, @@ -542,135 +409,221 @@ void gpu_reg_options(option_parser_t opp) option_parser_register(opp, "-gpgpu_ptx_inst_debug_thread_uid", OPT_INT32, &g_ptx_inst_debug_thread_uid, "Thread UID for executed instructions' debug output", "1"); - option_parser_register(opp, "-gpgpu_operand_collector", OPT_BOOL, &gpgpu_operand_collector, + option_parser_register(opp, "-gpgpu_ptx_convert_to_ptxplus", OPT_BOOL, + &g_ptx_convert_to_ptxplus, + "Convert embedded ptx to ptxplus", + "0"); + option_parser_register(opp, "-gpgpu_ptx_save_converted_ptxplus", OPT_BOOL, + &g_ptx_save_converted_ptxplus, + "Saved converted ptxplus to a file", + "0"); + option_parser_register(opp, "-gpgpu_operand_collector", OPT_BOOL, &m_shader_config->gpgpu_operand_collector, "Enable operand collector model (default = off)", "0"); - option_parser_register(opp, "-gpgpu_operand_collector_num_units", OPT_INT32, &gpgpu_operand_collector_num_units, + option_parser_register(opp, "-gpgpu_operand_collector_num_units", OPT_INT32, &m_shader_config->gpgpu_operand_collector_num_units, "number of collecture units (default = 4)", "4"); - option_parser_register(opp, "-gpgpu_operand_collector_num_units_sfu", OPT_INT32, &gpgpu_operand_collector_num_units_sfu, + option_parser_register(opp, "-gpgpu_operand_collector_num_units_sfu", OPT_INT32, &m_shader_config->gpgpu_operand_collector_num_units_sfu, "number of collecture units (default = 4)", "4"); - option_parser_register(opp, "-gpgpu_coalesce_arch", OPT_INT32, &gpgpu_coalesce_arch, + option_parser_register(opp, "-gpgpu_coalesce_arch", OPT_INT32, &m_shader_config->gpgpu_coalesce_arch, "Coalescing arch (default = 13, anything else is off for now)", "13"); addrdec_setoption(opp); L2c_options(opp); visualizer_options(opp); ptx_file_line_stats_options(opp); + + m_options_set = true; } ///////////////////////////////////////////////////////////////////////////// -inline int mem2device(int memid) { +int mem2device(int memid) +{ return memid + gpu_n_tpc; } ///////////////////////////////////////////////////////////////////////////// +void increment_x_then_y_then_z( dim3 &i, const dim3 &bound) +{ + i.x++; + if ( i.x >= bound.x ) { + i.x = 0; + i.y++; + if ( i.y >= bound.y ) { + i.y = 0; + if( i.z < bound.z ) + i.z++; + } + } +} + + +void gpgpu_sim::launch( kernel_info_t &kinfo ) +{ + unsigned cta_size = kinfo.threads_per_cta(); + if ( cta_size > m_shader_config->n_thread_per_shader ) { + printf("Execution error: Shader kernel CTA (block) size is too large for microarch config.\n"); + printf(" CTA size (x*y*z) = %u, max supported = %u\n", cta_size, + m_shader_config->n_thread_per_shader ); + printf(" => either change -gpgpu_shader argument in gpgpusim.config file or\n"); + printf(" modify the CUDA source to decrease the kernel block size.\n"); + abort(); + } + + m_running_kernels.push_back(kinfo); +} -/* Allocate memory for uArch structures */ -void init_gpu () +void gpgpu_sim::next_grid( unsigned &grid_num, class function_info *&entry ) +{ + 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() { - // initialize the GPU microarchitecture model - int i; + 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)); + m_memory_stats = NULL; +} +void set_ptx_warp_size(unsigned warp_size); + +void gpgpu_sim::init_gpu() +{ + assert( m_options_set ); + gpu_max_cycle = gpu_max_cycle_opt; - gpu_max_insn = gpu_max_insn_opt; + gpu_max_insn = gpu_max_insn_opt; - i = sscanf(gpgpu_shader_core_pipeline_opt,"%d:%d:%d", - &gpu_n_thread_per_shader, &warp_size, &pipe_simd_width); - gpu_n_warp_per_shader = gpu_n_thread_per_shader / warp_size; - num_warps_issuable = (int*) calloc(gpu_n_warp_per_shader+1, sizeof(int)); - num_warps_issuable_pershader = (int*) calloc(gpu_n_shader, sizeof(int)); - if (i == 2) { - pipe_simd_width = warp_size; - } else if (i == 3) { - assert(warp_size % pipe_simd_width == 0); + int ntok = sscanf(gpgpu_shader_core_pipeline_opt,"%d:%d", + &m_shader_config->n_thread_per_shader, + &m_shader_config->warp_size); + set_ptx_warp_size(m_shader_config->warp_size); + + m_shader_config->max_warps_per_shader = m_shader_config->n_thread_per_shader/m_shader_config->warp_size; + 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->shader_cycle_distro = (unsigned int*) calloc(m_shader_config->warp_size + 3, sizeof(unsigned int)); + + if(ntok != 2) { + printf("GPGPU-Sim uArch: error while parsing configuration string gpgpu_shader_core_pipeline_opt\n"); + abort(); } - sscanf(gpgpu_runtime_stat, "%d:%x", - &gpu_stat_sample_freq, &gpu_runtime_stat_flag); + sscanf(gpgpu_runtime_stat, "%d:%x", &gpu_stat_sample_freq, &gpu_runtime_stat_flag); + + m_shader_config->pdom_sched_type = m_pdom_sched_type; + m_shader_config->gpgpu_n_shmem_bank=16; - sc = (shader_core_ctx_t**) calloc(gpu_n_shader, sizeof(shader_core_ctx_t*)); - int mshr_que = gpu_n_mshr_per_thread; - for (i=0;(unsigned)i<gpu_n_shader;i++) { - sc[i] = shader_create("sh", i, /* shader id*/ - gpu_n_thread_per_shader, /* number of threads */ - mshr_que, /* number of MSHR per threads */ - fq_push, fq_has_buffer, gpgpu_simd_model); + 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(gpu_n_shader); + ptx_file_line_stats_create_exposed_latency_tracker(m_n_shader); // initialize dynamic warp formation scheduler int dwf_lut_size, dwf_lut_assoc; sscanf(gpgpu_dwf_hw_opt,"%d:%d", &dwf_lut_size, &dwf_lut_assoc); char *dwf_hw_policy_opt = strchr(gpgpu_dwf_hw_opt, ';'); int insn_size = 1; // for cuda-sim - create_dwf_schedulers(gpu_n_shader, dwf_lut_size, dwf_lut_assoc, - warp_size, pipe_simd_width, - gpu_n_thread_per_shader, insn_size, + create_dwf_schedulers(m_n_shader, dwf_lut_size, dwf_lut_assoc, + m_shader_config->warp_size, m_shader_config->warp_size, + m_shader_config->n_thread_per_shader, insn_size, gpgpu_dwf_heuristic, dwf_hw_policy_opt ); - gpgpu_no_divg_load = gpgpu_no_divg_load && (gpgpu_simd_model == DWF); - // always use no diverge on load for PDOM and NAIVE - gpgpu_no_divg_load = gpgpu_no_divg_load || (gpgpu_simd_model == POST_DOMINATOR || gpgpu_simd_model == NO_RECONVERGE); - if (gpgpu_no_divg_load) { - //init_warp_tracker(); - printf("warp_tracker_pool size = %d\n", get_warp_tracker_pool().size()); - } + // always use no diverge on load for stack based SIMT execution (PDOM) + m_shader_config->gpgpu_no_divg_load = (m_shader_config->model != DWF) || + (m_shader_config->gpgpu_no_divg_load && (m_shader_config->model == DWF)); + m_shader_config->m_using_dwf_rrstage = (m_shader_config->model == DWF); + m_shader_config->using_commit_queue = (m_shader_config->model == DWF || m_shader_config->model == POST_DOMINATOR); - assert(gpu_n_shader % gpu_concentration == 0); - gpu_n_tpc = gpu_n_shader / gpu_concentration; + m_shader_config->gpgpu_dwf_rr_stage_n_reg_banks=8; - dram = (dram_t**) calloc(gpu_n_mem, sizeof(dram_t*)); - // L2request = (mem_fetch_t**) calloc(gpu_n_mem, sizeof(mem_fetch_t*)); - addrdec_setnchip(gpu_n_mem); - unsigned int nbk,tCCD,tRRD,tRCD,tRAS,tRP,tRC,CL,WL,tWTR; - sscanf(gpgpu_dram_timing_opt,"%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",&nbk,&tCCD,&tRRD,&tRCD,&tRAS,&tRP,&tRC,&CL,&WL,&tWTR); - gpu_mem_n_bk = nbk; - for (i=0;(unsigned)i<gpu_n_mem;i++) { - dram[i] = dram_create(i, nbk, tCCD, tRRD, tRCD, tRAS, tRP, tRC, - CL, WL, gpgpu_dram_burst_length/*BL*/, tWTR, gpgpu_dram_buswidth/*busW*/, - gpgpu_dram_sched_queue_size, gpgpu_dram_scheduler); - if (gpgpu_cache_dl2_opt) - L2c_create(dram[i], gpgpu_cache_dl2_opt); - } - dram_log(CREATELOG); - if (gpgpu_cache_dl2_opt && 1) { - L2c_log(CREATELOG); - } - concurrent_row_access = (unsigned int**) calloc(gpu_n_mem, sizeof(unsigned int*)); - num_activates = (unsigned int**) calloc(gpu_n_mem, sizeof(unsigned int*)); - row_access = (unsigned int**) calloc(gpu_n_mem, sizeof(unsigned int*)); - max_conc_access2samerow = (unsigned int**) calloc(gpu_n_mem, sizeof(unsigned int*)); - max_servicetime2samerow = (unsigned int**) calloc(gpu_n_mem, sizeof(unsigned int*)); + assert(m_n_shader % gpu_concentration == 0); + gpu_n_tpc = m_n_shader / gpu_concentration; + + 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++) + 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_partition_unit[i]->set_stats(m_memory_stats); - for (i=0;(unsigned)i<gpu_n_mem ;i++ ) { - concurrent_row_access[i] = (unsigned int*) calloc(gpu_mem_n_bk, sizeof(unsigned int)); - row_access[i] = (unsigned int*) calloc(gpu_mem_n_bk, sizeof(unsigned int)); - num_activates[i] = (unsigned int*) calloc(gpu_mem_n_bk, sizeof(unsigned int)); - max_conc_access2samerow[i] = (unsigned int*) calloc(gpu_mem_n_bk, sizeof(unsigned int)); - max_servicetime2samerow[i] = (unsigned int*) calloc(gpu_mem_n_bk, sizeof(unsigned int)); + 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*)); + + for (unsigned i=0;i<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)); + max_conc_access2samerow[i] = (unsigned int*) calloc(m_memory_config->gpu_mem_n_bk, sizeof(unsigned int)); + max_servicetime2samerow[i] = (unsigned int*) calloc(m_memory_config->gpu_mem_n_bk, sizeof(unsigned int)); } - memlatstat_init(); + m_memory_stats = new memory_stats_t(m_n_mem,m_n_shader,m_shader_config,m_memory_config); - L2c_init_stat(); - max_return_queue_length = (unsigned int*) calloc(gpu_n_shader, sizeof(unsigned int)); - icnt_init(gpu_n_tpc, gpu_n_mem); + m_shader_stats->max_return_queue_length = (unsigned int*) calloc(m_n_shader, sizeof(unsigned int)); - common_clock = 0; + icnt_init(gpu_n_tpc, 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"); + init_clock_domains(); +} + +int gpgpu_sim::shared_mem_size() const +{ + return m_shader_config->gpgpu_shmem_size; +} + +int gpgpu_sim::num_registers_per_core() const +{ + return m_shader_config->gpgpu_shader_registers; } +int gpgpu_sim::wrp_size() const +{ + return m_shader_config->warp_size; +} +int gpgpu_sim::shader_clock() const +{ + return core_freq/1000; +} -void gpu_print_stat(); +void gpgpu_sim::set_prop( cudaDeviceProp *prop ) +{ + m_cuda_properties = prop; +} -void init_clock_domains(void ) { +const struct cudaDeviceProp *gpgpu_sim::get_prop() const +{ + return m_cuda_properties; +} + +enum divergence_support_t gpgpu_sim::simd_model() const +{ + return m_shader_config->model; +} + +void gpgpu_sim::init_clock_domains(void ) +{ sscanf(gpgpu_clock_domains,"%lf:%lf:%lf:%lf", &core_freq, &icnt_freq, &l2_freq, &dram_freq); core_freq = core_freq MhZ; @@ -689,22 +642,21 @@ void init_clock_domains(void ) { printf("GPGPU-Sim uArch: clock periods: %.20lf:%.20lf:%.20lf:%.20lf\n",core_period,icnt_period,l2_period,dram_period); } -void reinit_clock_domains(void) +void gpgpu_sim::reinit_clock_domains(void) { - core_time = 0 ; - dram_time = 0 ; + core_time = 0; + dram_time = 0; icnt_time = 0; l2_time = 0; } -void init_once(void ) { - init_clock_domains(); -} - // return the number of cycle required to run all the trace on the gpu -unsigned int run_gpu_sim(int grid_num) +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()); int not_completed; int mem_busy; @@ -717,28 +669,17 @@ unsigned int run_gpu_sim(int grid_num) g_next_mf_request_uid = 1; more_thread = 1; gpu_sim_insn = 0; - gpu_sim_insn_no_ld_const = 0; + m_shader_stats->gpu_sim_insn_no_ld_const = 0; + m_shader_stats->gpu_completed_thread = 0; - gpu_completed_thread = 0; - - g_nthreads_issued = 0; - - static int one_time_inits_done = 0 ; - if (!one_time_inits_done ) { - init_once(); - } reinit_clock_domains(); - assert(gpgpu_spread_blocks_across_cores); // this seems to be required, so let's make it explicit - set_option_gpgpu_spread_blocks_across_cores(gpgpu_spread_blocks_across_cores); - set_param_gpgpu_num_shaders(gpu_n_shader); - for (unsigned i=0;i<gpu_n_shader;i++) { - sc[i]->not_completed = 0; - shader_reinit(sc[i],0,sc[i]->n_threads); - } + 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); if (gpu_max_cta_opt != 0) { g_total_cta_left = gpu_max_cta_opt; } else { - g_total_cta_left = ptx_sim_grid_size(); + g_total_cta_left = m_the_kernel.num_blocks(); } if (gpu_max_cta_opt != 0) { // the maximum number of CTA has been reached, stop any further simulation @@ -756,75 +697,57 @@ unsigned int run_gpu_sim(int grid_num) // refind the diverge/reconvergence pairs dwf_reset_reconv_pt(); - find_reconvergence_points(); - - dwf_process_reconv_pts(); - dwf_reinit_schedulers(gpu_n_shader); + dwf_process_reconv_pts(entry.entry()); + dwf_reinit_schedulers(m_n_shader); // initialize the control-flow, memory access, memory latency logger - create_thread_CFlogger( gpu_n_shader, gpu_n_thread_per_shader, ptx_kernel_program_size(), 0, gpgpu_cflog_interval ); - shader_CTA_count_create( gpu_n_shader, gpgpu_cflog_interval); + 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); if (gpgpu_cflog_interval != 0) { - insn_warp_occ_create( gpu_n_shader, warp_size, ptx_kernel_program_size() ); - shader_warp_occ_create( gpu_n_shader, warp_size, gpgpu_cflog_interval); - shader_mem_acc_create( gpu_n_shader, gpu_n_mem, 4, gpgpu_cflog_interval); - shader_mem_lat_create( gpu_n_shader, gpgpu_cflog_interval); - shader_cache_access_create( gpu_n_shader, 3, gpgpu_cflog_interval); + 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); set_spill_interval (gpgpu_cflog_interval * 40); } // calcaulte the max cta count and cta size for local memory address mapping - gpu_max_cta_per_shader = max_cta_per_shader(sc[0]); + m_shader_config->gpu_max_cta_per_shader = m_sc[0]->max_cta(entry.entry()); //gpu_max_cta_per_shader is limited by number of CTAs if not enough - if (ptx_sim_grid_size() < gpu_max_cta_per_shader*gpu_n_shader) { - gpu_max_cta_per_shader = (ptx_sim_grid_size() / gpu_n_shader); - if (ptx_sim_grid_size() % gpu_n_shader) - gpu_max_cta_per_shader++; + 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) + m_shader_config->gpu_max_cta_per_shader++; } - unsigned int gpu_cta_size = ptx_sim_cta_size(); - gpu_padded_cta_size = (gpu_cta_size%32) ? 32*((gpu_cta_size/32)+1) : gpu_cta_size; + unsigned int gpu_cta_size = m_the_kernel.threads_per_cta(); + m_shader_config->gpu_padded_cta_size = (gpu_cta_size%32) ? 32*((gpu_cta_size/32)+1) : gpu_cta_size; if (g_network_mode) { icnt_init_grid(); } - // Initialize dram delay queues - dram_delay_queues.resize(gpu_n_mem); - - last_gpu_sim_insn = 0; - // add this condition as well? (gpgpu_n_processed_writes < gpgpu_n_sent_writes) while (not_completed || mem_busy || icnt2mem_busy) { - gpu_sim_loop(grid_num); - + gpu_sim_loop(); not_completed = 0; - for (unsigned i=0;i<gpu_n_shader;i++) { - not_completed += sc[i]->not_completed; - } - // dram_busy just check the request queue length into the dram - // to make sure all the memory requests (esp the writes) are done + for (unsigned i=0;i<m_n_shader;i++) + not_completed += m_sc[i]->get_not_completed(); mem_busy = 0; - for (unsigned i=0;i<gpu_n_mem;i++) { - mem_busy += dram_busy(dram[i]); - } - // icnt to the memory should clean of any pending tranfers as well - icnt2mem_busy = icnt_busy( ); - - if (gpu_max_cycle && (gpu_tot_sim_cycle + gpu_sim_cycle) >= gpu_max_cycle) { + for (unsigned i=0;i<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) break; - } - if (gpu_max_insn && (gpu_tot_sim_insn + gpu_sim_insn) >= gpu_max_insn) { + if (gpu_max_insn && (gpu_tot_sim_insn + gpu_sim_insn) >= gpu_max_insn) break; - } - if (gpu_deadlock_detect && gpu_deadlock) { + if (gpu_deadlock_detect && gpu_deadlock) break; - } - } - memlatstat_lat_pw(); + m_memory_stats->memlatstat_lat_pw(m_n_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 += gpu_completed_thread; + gpu_tot_completed_thread += m_shader_stats->gpu_completed_thread; ptx_file_line_stats_write_file(); @@ -836,37 +759,60 @@ unsigned int run_gpu_sim(int grid_num) icnt_overal_stat(); printf("----------------------------END-of-Interconnect-DETAILS-------------------------" ); } - if (gpgpu_memlatency_stat & GPU_MEMLATSTAT_QUEUELOGS ) { - dramqueue_latency_log_dump(); - dram_log(DUMPLOG); - if (gpgpu_cache_dl2_opt) { - L2c_log(DUMPLOG); + if (m_memory_config->gpgpu_memlatency_stat & GPU_MEMLATSTAT_QUEUELOGS ) { + for (unsigned i=0;i<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++) + m_memory_partition_unit[i]->L2c_log(DUMPLOG); L2c_latency_log_dump(); } } -#define DEADLOCK 0 if (gpu_deadlock_detect && gpu_deadlock) { fflush(stdout); printf("GPGPU-Sim uArch: ERROR ** deadlock detected: last writeback @ gpu_sim_cycle %u (+ gpu_tot_sim_cycle %u) (%u cycles ago)\n", (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(); + if( not_completed ) { + if ( !num_cores ) { + printf("GPGPU-Sim uArch: DEADLOCK shader cores no longer committing instructions [core(# threads)]:\n" ); + printf("GPGPU-Sim uArch: DEADLOCK %u(%u)", i, not_completed); + } else if (num_cores < 8 ) { + printf(" %u(%u)", i, not_completed); + } else if (num_cores == 8 ) { + printf(" + others ... "); + } + num_cores++; + } + } + printf("\n"); + for (unsigned i=0;i<m_n_mem;i++) { + mem_busy += m_memory_partition_unit[i]->busy(); + if( mem_busy ) + printf("GPGPU-Sim uArch DEADLOCK: memory partition %u still busy\n", i); + } + if( icnt_busy() ) + printf("GPGPU-Sim uArch DEADLOCK: iterconnect contains traffic\n"); + printf("\nRe-run the simulator in gdb and use debug routines in .gdbinit to debug this\n"); fflush(stdout); - assert(DEADLOCK); + abort(); } return gpu_sim_cycle; } -void gpu_print_stat() +void gpgpu_sim::gpu_print_stat() const { unsigned i; - int j,k; printf("gpu_sim_cycle = %lld\n", gpu_sim_cycle); printf("gpu_sim_insn = %lld\n", gpu_sim_insn); - printf("gpu_sim_no_ld_const_insn = %lld\n", gpu_sim_insn_no_ld_const); + printf("gpu_sim_no_ld_const_insn = %lld\n", m_shader_stats->gpu_sim_insn_no_ld_const); printf("gpu_ipc = %12.4f\n", (float)gpu_sim_insn / gpu_sim_cycle); - printf("gpu_completed_thread = %lld\n", gpu_completed_thread); + printf("gpu_completed_thread = %lld\n", m_shader_stats->gpu_completed_thread); printf("gpu_tot_sim_cycle = %lld\n", gpu_tot_sim_cycle); printf("gpu_tot_sim_insn = %lld\n", gpu_tot_sim_insn); printf("gpu_tot_ipc = %12.4f\n", (float)gpu_tot_sim_insn / gpu_tot_sim_cycle); @@ -876,32 +822,29 @@ void gpu_print_stat() printf("gpgpu_n_processed_writes = %d\n", gpgpu_n_processed_writes); // performance counter for stalls due to congestion. - printf("gpu_stall_by_MSHRwb= %d\n", gpu_stall_by_MSHRwb); - printf("gpu_stall_shd_mem = %d\n", gpu_stall_shd_mem ); + printf("gpu_stall_by_MSHRwb= %d\n", m_shader_stats->gpu_stall_by_MSHRwb); + printf("gpu_stall_shd_mem = %d\n", m_shader_stats->gpu_stall_shd_mem ); printf("gpu_stall_wr_back = %d\n", gpu_stall_wr_back ); printf("gpu_stall_dramfull = %d\n", gpu_stall_dramfull); printf("gpu_stall_icnt2sh = %d\n", gpu_stall_icnt2sh ); - printf("gpu_stall_sh2icnt = %d\n", gpu_stall_sh2icnt ); + printf("gpu_stall_sh2icnt = %d\n", m_shader_stats->gpu_stall_sh2icnt ); // performance counter that are not local to one shader shader_print_accstats(stdout); - memlatstat_print(); + 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<gpu_n_shader;i++) { - printf("%d ", max_return_queue_length[i]); + for (unsigned i=0;i<m_n_shader;i++) { + printf("%d ", m_shader_stats->max_return_queue_length[i]); } printf("\n"); // merge misses - printf("L1 read misses = %d\n", L1_read_miss); - printf("L1 write misses = %d\n", L1_write_miss); - printf("L1 write hit on misses = %d\n", L1_write_hit_on_miss); - printf("L1 writebacks = %d\n", L1_writeback); - printf("L1 texture misses = %d\n", L1_texture_miss); - printf("L1 const misses = %d\n", L1_const_miss); - printf("L2_write_miss = %d\n", L2_write_miss); - printf("L2_write_hit = %d\n", L2_write_hit); - printf("L2_read_miss = %d\n", L2_read_miss); - printf("L2_read_hit = %d\n", L2_read_hit); + printf("L1 read misses = %d\n", m_shader_stats->L1_read_miss); + printf("L1 write misses = %d\n", m_shader_stats->L1_write_miss); + printf("L1 write hit on misses = %d\n", m_shader_stats->L1_write_hit_on_miss); + printf("L1 writebacks = %d\n", m_shader_stats->L1_writeback); + printf("L1 texture misses = %d\n", m_shader_stats->L1_texture_miss); + printf("L1 const misses = %d\n", m_shader_stats->L1_const_miss); + m_memory_stats->print(stdout); printf("made_read_mfs = %d\n", made_read_mfs); printf("made_write_mfs = %d\n", made_write_mfs); printf("freed_read_mfs = %d\n", freed_read_mfs); @@ -909,66 +852,51 @@ void gpu_print_stat() printf("freed_L2write_mfs = %d\n", freed_L2write_mfs); printf("freed_dummy_read_mfs = %d\n", freed_dummy_read_mfs); - printf("gpgpu_n_mem_read_local = %d\n", gpgpu_n_mem_read_local); - printf("gpgpu_n_mem_write_local = %d\n", gpgpu_n_mem_write_local); - printf("gpgpu_n_mem_read_global = %d\n", gpgpu_n_mem_read_global); - printf("gpgpu_n_mem_write_global = %d\n", gpgpu_n_mem_write_global); - printf("gpgpu_n_mem_texture = %d\n", gpgpu_n_mem_texture); - printf("gpgpu_n_mem_const = %d\n", gpgpu_n_mem_const); + printf("gpgpu_n_mem_read_local = %d\n", m_shader_stats->gpgpu_n_mem_read_local); + printf("gpgpu_n_mem_write_local = %d\n", m_shader_stats->gpgpu_n_mem_write_local); + printf("gpgpu_n_mem_read_global = %d\n", m_shader_stats->gpgpu_n_mem_read_global); + printf("gpgpu_n_mem_write_global = %d\n", m_shader_stats->gpgpu_n_mem_write_global); + printf("gpgpu_n_mem_texture = %d\n", m_shader_stats->gpgpu_n_mem_texture); + printf("gpgpu_n_mem_const = %d\n", m_shader_stats->gpgpu_n_mem_const); printf("max_n_mshr_used = "); - for (unsigned i=0; i< gpu_n_shader; i++) printf("%d ", get_max_mshr_used(sc[i])); + for (unsigned i=0; i< m_n_shader; i++) printf("%d ", m_sc[i]->get_max_mshr_used() ); printf("\n"); - if (gpgpu_cache_dl2_opt) { - L2c_print_stat( ); + if (m_memory_config->gpgpu_cache_dl2_opt) { + m_memory_stats->L2c_print_stat( m_n_mem ); } - for (unsigned i=0;i<gpu_n_mem;i++) { - dram_print(dram[i],stdout); - } - - for (i=0, j=0, k=0;i<gpu_n_shader;i++) { - shd_cache_print(sc[i]->L1cache,stdout); - j+=sc[i]->L1cache->miss; - k+=sc[i]->L1cache->access; - } - printf("L1 Data Cache Total Miss Rate = %0.3f\n", (float)j/k); + for (unsigned i=0;i<m_n_mem;i++) + m_memory_partition_unit[i]->print(stdout); - for (i=0,j=0,k=0;i<gpu_n_shader;i++) { - shd_cache_print(sc[i]->L1texcache,stdout); - j+=sc[i]->L1texcache->miss; - k+=sc[i]->L1texcache->access; - } - printf("L1 Texture Cache Total Miss Rate = %0.3f\n", (float)j/k); + unsigned a,m; + for (unsigned i=0, a=0, m=0;i<m_n_shader;i++) + m_sc[i]->L1cache_print(stdout,a,m); + printf("L1 Data Cache Total Miss Rate = %0.3f\n", (float)m/a); + for (i=0,a=0,m=0;i<m_n_shader;i++) + m_sc[i]->L1texcache_print(stdout,a,m); + printf("L1 Texture Cache Total Miss Rate = %0.3f\n", (float)m/a); + for (i=0,a=0,m=0;i<m_n_shader;i++) + m_sc[i]->L1constcache_print(stdout,a,m); + printf("L1 Const Cache Total Miss Rate = %0.3f\n", (float)m/a); - for (i=0,j=0,k=0;i<gpu_n_shader;i++) { - shd_cache_print(sc[i]->L1constcache,stdout); - j+=sc[i]->L1constcache->miss; - k+=sc[i]->L1constcache->access; - } - printf("L1 Const Cache Total Miss Rate = %0.3f\n", (float)j/k); - - if (gpgpu_cache_dl2_opt) { + if (m_memory_config->gpgpu_cache_dl2_opt) L2c_print_cache_stat(); - } printf("n_regconflict_stall = %d\n", n_regconflict_stall); - if (gpgpu_simd_model == DWF) { + if (m_shader_config->model == DWF) { dwf_print_stat(stdout); } - if (gpgpu_simd_model == POST_DOMINATOR) { + if (m_shader_config->model == POST_DOMINATOR) { printf("num_warps_issuable:"); - for (unsigned i=0;i<(gpu_n_warp_per_shader+1);i++) { - printf("%d ", num_warps_issuable[i]); + for (unsigned i=0;i<(m_shader_config->max_warps_per_shader+1);i++) { + printf("%d ", m_shader_stats->num_warps_issuable[i]); } printf("\n"); } - if (gpgpu_strict_simd_wrbk) { - printf("warp_conflict_at_writeback = %d\n", warp_conflict_at_writeback); - } - printf("gpgpu_commit_pc_beyond_two = %d\n", gpgpu_commit_pc_beyond_two); + printf("gpgpu_commit_pc_beyond_two = %d\n", m_shader_stats->gpgpu_commit_pc_beyond_two); print_shader_cycle_distro( stdout ); @@ -987,67 +915,111 @@ void gpu_print_stat() fflush(stdout); } -//////////////////////////////////////////////////////////////////////////////////// -// Wrapper function for shader cores' memory system: -//////////////////////////////////////////////////////////////////////////////////// -// a hack to make the size of a packet discrete multiples of the interconnect's flit_size. -static inline -unsigned int fill_to_next_flit(unsigned int size) +// performance counter that are not local to one shader +void gpgpu_sim::shader_print_accstats( FILE* fout ) const { - assert (g_network_mode == INTERSIM); - return size; -} + fprintf(fout, "gpgpu_n_load_insn = %d\n", m_shader_stats->gpgpu_n_load_insn); + fprintf(fout, "gpgpu_n_store_insn = %d\n", m_shader_stats->gpgpu_n_store_insn); + fprintf(fout, "gpgpu_n_shmem_insn = %d\n", m_shader_stats->gpgpu_n_shmem_insn); + fprintf(fout, "gpgpu_n_tex_insn = %d\n", m_shader_stats->gpgpu_n_tex_insn); + fprintf(fout, "gpgpu_n_const_mem_insn = %d\n", m_shader_stats->gpgpu_n_const_insn); + fprintf(fout, "gpgpu_n_param_mem_insn = %d\n", m_shader_stats->gpgpu_n_param_insn); + fprintf(fout, "gpgpu_n_shmem_bkconflict = %d\n", m_shader_stats->gpgpu_n_shmem_bkconflict); + fprintf(fout, "gpgpu_n_cache_bkconflict = %d\n", m_shader_stats->gpgpu_n_cache_bkconflict); + fprintf(fout, "gpgpu_n_intrawarp_mshr_merge = %d\n", m_shader_stats->gpgpu_n_intrawarp_mshr_merge); + fprintf(fout, "gpgpu_n_cmem_portconflict = %d\n", m_shader_stats->gpgpu_n_cmem_portconflict); -unsigned char check_icnt_has_buffer(unsigned long long int *addr, int *bsize, - int n_addr, int sid ) -{ - addrdec_t tlx; - static unsigned int *req_buffer = NULL; - //the req_buf size can be equal to gpu_n_mem ; gpu_n_shader is added to make it compatible - //with the case where a mem controller is sending to shd - if (!req_buffer) req_buffer = (unsigned int*)malloc((gpu_n_mem+gpu_n_tpc)*sizeof(unsigned int)); - memset(req_buffer, 0, (gpu_n_mem+gpu_n_tpc)*sizeof(unsigned int)); + fprintf(fout, "gpgpu_n_partial_writes = %d\n", m_shader_stats->gpgpu_n_partial_writes); - // aggregate all buffer requirement of all memory accesses by dram chips - for (int i=0; i< n_addr; i++) { - addrdec_tlx(addr[i],&tlx); - req_buffer[tlx.chip] += fill_to_next_flit(bsize[i]); - } + fprintf(fout, "gpgpu_stall_shd_mem[c_mem][bk_conf] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[C_MEM][BK_CONF]); + fprintf(fout, "gpgpu_stall_shd_mem[c_mem][mshr_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[C_MEM][MSHR_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[c_mem][icnt_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[C_MEM][ICNT_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[t_mem][mshr_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[T_MEM][MSHR_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[t_mem][icnt_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[T_MEM][ICNT_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[s_mem][bk_conf] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[S_MEM][BK_CONF]); + fprintf(fout, "gpgpu_stall_shd_mem[gl_mem][bk_conf] = %d\n", + m_shader_stats->gpu_stall_shd_mem_breakdown[G_MEM_LD][BK_CONF] + + m_shader_stats->gpu_stall_shd_mem_breakdown[G_MEM_ST][BK_CONF] + + m_shader_stats->gpu_stall_shd_mem_breakdown[L_MEM_LD][BK_CONF] + + m_shader_stats->gpu_stall_shd_mem_breakdown[L_MEM_ST][BK_CONF] + ); // coalescing stall at data cache + fprintf(fout, "gpgpu_stall_shd_mem[gl_mem][coal_stall] = %d\n", + m_shader_stats->gpu_stall_shd_mem_breakdown[G_MEM_LD][COAL_STALL] + + m_shader_stats->gpu_stall_shd_mem_breakdown[G_MEM_ST][COAL_STALL] + + m_shader_stats->gpu_stall_shd_mem_breakdown[L_MEM_LD][COAL_STALL] + + m_shader_stats->gpu_stall_shd_mem_breakdown[L_MEM_ST][COAL_STALL] + ); // coalescing stall + bank conflict at data cache + fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][mshr_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[G_MEM_LD][MSHR_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][icnt_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[G_MEM_LD][ICNT_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][wb_icnt_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[G_MEM_LD][WB_ICNT_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][wb_rsrv_fail] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[G_MEM_LD][WB_CACHE_RSRV_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][mshr_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[G_MEM_ST][MSHR_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][icnt_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[G_MEM_ST][ICNT_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][wb_icnt_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[G_MEM_ST][WB_ICNT_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][wb_rsrv_fail] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[G_MEM_ST][WB_CACHE_RSRV_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][mshr_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[L_MEM_LD][MSHR_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][icnt_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[L_MEM_LD][ICNT_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_icnt_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[L_MEM_LD][WB_ICNT_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_rsrv_fail] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[L_MEM_LD][WB_CACHE_RSRV_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[l_mem_st][mshr_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[L_MEM_ST][MSHR_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[l_mem_st][icnt_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[L_MEM_ST][ICNT_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_icnt_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[L_MEM_ST][WB_ICNT_RC_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_rsrv_fail] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[L_MEM_ST][WB_CACHE_RSRV_FAIL]); - int tpc_id = sid / gpu_concentration; + fprintf(fout, "gpu_reg_bank_conflict_stalls = %d\n", m_shader_stats->gpu_reg_bank_conflict_stalls); +} - return icnt_has_buffer(tpc_id, req_buffer); +unsigned gpgpu_sim::threads_per_core() const +{ + return m_shader_config->n_thread_per_shader; } -unsigned char single_check_icnt_has_buffer(int chip, int sid, unsigned char is_write ) +void gpgpu_sim::mem_instruction_stats(inst_t* warp) { - static unsigned int *req_buffer = NULL; - //the req_buf size can be equal to gpu_n_mem ; gpu_n_shader is added to make it compatible - //with the case where a mem controller is sending to shd - if (!req_buffer) req_buffer = (unsigned int*)malloc((gpu_n_mem+gpu_n_tpc)*sizeof(unsigned int)); - memset(req_buffer, 0, (gpu_n_mem+gpu_n_tpc)*sizeof(unsigned int)); - - // aggregate all buffer requirement of all memory accesses by dram chips - - int b_size; - if (is_write) - b_size = sc[sid]->L1cache->line_sz; - else - b_size = READ_PACKET_SIZE; - req_buffer[chip] += fill_to_next_flit(b_size); - - int tpc_id = sid / gpu_concentration; - - return icnt_has_buffer(tpc_id, req_buffer); + for (unsigned i=0; i< (unsigned) m_shader_config->warp_size; i++) { + if (warp[i].hw_thread_id == -1) continue; //bubble + //this breaks some encapsulation: the is_[space] functions, if you change those, change this. + bool store = is_store(warp[i]); + switch (warp[i].space.get_type()) { + case undefined_space: + case reg_space: + break; + case shared_space: + m_shader_stats->gpgpu_n_shmem_insn++; + break; + case const_space: + m_shader_stats->gpgpu_n_const_insn++; + break; + case param_space_kernel: + case param_space_local: + m_shader_stats->gpgpu_n_param_insn++; + break; + case tex_space: + m_shader_stats->gpgpu_n_tex_insn++; + break; + case global_space: + case local_space: + if (store){ + m_shader_stats->gpgpu_n_store_insn++; + } else { + m_shader_stats->gpgpu_n_load_insn++; + } + break; + default: + abort(); + } + } } -int max_n_addr = 0; +//////////////////////////////////////////////////////////////////////////////////// +// Wrapper function for shader cores' memory system: +//////////////////////////////////////////////////////////////////////////////////// // Check the memory system for buffer availability -unsigned char fq_has_buffer(unsigned long long int addr, int bsize, bool write, int sid ) +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; @@ -1055,76 +1027,36 @@ unsigned char fq_has_buffer(unsigned long long int addr, int bsize, bool write, if (!write) { rsize = READ_PACKET_SIZE; } - return check_icnt_has_buffer(&addr, &rsize, 1, sid); + return check_icnt_has_buffer(addr, rsize, sid); } -// Takes in memory address and their parameters and pushes to the fetch queue -unsigned char fq_push(unsigned long long int addr, int bsize, unsigned char write, partial_write_mask_t partial_write_mask, - int sid, int wid, mshr_entry* mshr, int cache_hits_waiting, - enum mem_access_type mem_acc, address_type pc) +unsigned char gpgpu_sim::check_icnt_has_buffer(unsigned long long int addr, int bsize, int sid ) { - mem_fetch_t *mf; - - mf = (mem_fetch_t*) calloc(1,sizeof(mem_fetch_t)); - mf->request_uid = g_next_mf_request_uid++; - mf->addr = addr; - mf->nbytes_L1 = bsize; - mf->sid = sid; - mf->source_node = sid / gpu_concentration; - mf->wid = wid; - mf->cache_hits_waiting = cache_hits_waiting; - mf->txbytes_L1 = 0; - mf->rxbytes_L1 = 0; - mf->mshr = mshr; - if (mshr) mshr->mf = (void*)mf; // for debugging - mf->write = write; + int tpc_id = sid / gpu_concentration; + return icnt_has_buffer(tpc_id, bsize); +} - if (write) - made_write_mfs++; - else - made_read_mfs++; - memlatstat_start(mf); - addrdec_tlx(addr,&mf->tlx); - mf->bank = mf->tlx.bk; - mf->chip = mf->tlx.chip; - if (gpgpu_cache_dl2_opt) - mf->nbytes_L2 = L2c_get_linesize( dram[mf->tlx.chip] ); +unsigned gpgpu_sim::get_L2_linesize() const +{ + if (m_memory_partition_unit[0]->has_cache()) + return m_memory_partition_unit[0]->L2c_get_linesize(); else - mf->nbytes_L2 = 0; - mf->txbytes_L2 = 0; - mf->rxbytes_L2 = 0; - - mf->write_mask = partial_write_mask; - if (!write) assert(partial_write_mask == NO_PARTIAL_WRITE); - - // stat collection codes - mf->mem_acc = mem_acc; - mf->pc = pc; - - switch (mem_acc) { - case CONST_ACC_R: gpgpu_n_mem_const++; break; - case TEXTURE_ACC_R: gpgpu_n_mem_texture++; break; - case GLOBAL_ACC_R: gpgpu_n_mem_read_global++; break; - case GLOBAL_ACC_W: gpgpu_n_mem_write_global++; break; - case LOCAL_ACC_R: gpgpu_n_mem_read_local++; break; - case LOCAL_ACC_W: gpgpu_n_mem_write_local++; break; - default: assert(0); - } - - return(issue_mf_from_fq(mf)); - + return 0; } -int issue_mf_from_fq(mem_fetch_t *mf){ +int gpgpu_sim::issue_mf_from_fq(mem_fetch *mf) +{ + m_memory_stats->memlatstat_start(mf); int destination; // where is the next level of memory? destination = mf->tlx.chip; int tpc_id = mf->sid / gpu_concentration; - if (mf->mshr) mshr_update_status(mf->mshr,IN_ICNT2MEM); - if (!mf->write) { + if (mf->mshr) mf->mshr->set_status(IN_ICNT2MEM); + if (!mf->m_write) { mf->type = RD_REQ; assert( mf->timestamp == (gpu_sim_cycle+gpu_tot_sim_cycle) ); - time_vector_update(mf->mshr->insts[0].uid, MR_ICNT_PUSHED, gpu_sim_cycle+gpu_tot_sim_cycle, mf->type ); + if( mf->mshr && mf->mshr->has_inst() ) + time_vector_update(mf->mshr->get_insts_uid(), MR_ICNT_PUSHED, gpu_sim_cycle+gpu_tot_sim_cycle, mf->type ); icnt_push(tpc_id, mem2device(destination), (void*)mf, READ_PACKET_SIZE); } else { mf->type = WT_REQ; @@ -1137,260 +1069,235 @@ int issue_mf_from_fq(mem_fetch_t *mf){ return 0; } -inline void fill_shd_L1_with_new_line(shader_core_ctx_t * sc, mem_fetch_t * mf) { - unsigned long long int repl_addr = -1; +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 ) - memlatstat_read_done(mf); - - mshr_return_from_mem(sc, mf->mshr); - - if (mf->mshr->istexture) { - shd_cache_fill(sc->L1texcache,mf->addr,sc->gpu_cycle); - repl_addr = -1; - } else if (mf->mshr->isconst) { - shd_cache_fill(sc->L1constcache,mf->addr,sc->gpu_cycle); - repl_addr = -1; + if (mf->mshr->isinst()) { + shd_cache_fill(m_L1I,mf->addr,gpu_sim_cycle+gpu_tot_sim_cycle); + m_warp[mf->mshr->get_warp_id()].clear_imiss_pending(); + delete mf->mshr; + mf->mshr=NULL; } else { - if (!gpgpu_no_dl1) { - //if we are doing a writeback cache we may have marked off a mask in the mshr - //only write into the cache unmasked bytes. - //since this doesn't affect timing we don't actually do it. - repl_addr = shd_cache_fill(sc->L1cache,mf->addr,sc->gpu_cycle); - } + m_mshr_unit->mshr_return_from_mem(mf->mshr); + if (mf->mshr->istexture()) + shd_cache_fill(m_L1T,mf->addr,gpu_sim_cycle+gpu_tot_sim_cycle); + else if (mf->mshr->isconst()) + shd_cache_fill(m_L1C,mf->addr,gpu_sim_cycle+gpu_tot_sim_cycle); + else if (!m_config->gpgpu_no_dl1) + shd_cache_fill(m_L1D,mf->addr,gpu_sim_cycle+gpu_tot_sim_cycle); } - freed_read_mfs++; - free(mf); + delete mf; } -unsigned char fq_pop(int tpc_id) +void shader_core_ctx::store_ack( class mem_fetch *mf ) { - mem_fetch_t *mf; - - mf = (mem_fetch_t*) icnt_pop(tpc_id); - - // if there is a memory fetch request coming back, forward it to the proper shader core - if (mf) { - assert(mf->type == REPLY_DATA); - time_vector_update(mf->mshr->insts[0].uid ,MR_2SH_FQ_POP,gpu_sim_cycle+gpu_tot_sim_cycle, mf->type ) ; - fill_shd_L1_with_new_line(sc[mf->sid], mf); + if (!strcmp("GT200",m_config->pipeline_model) ) { + unsigned warp_id = mf->wid; + m_warp[warp_id].dec_store_req(); } - return 0; } -//////////////////////////////////////////////////////////////////////////////////////////////// - -int issue_block2core( shader_core_ctx_t *shdr, int grid_num ) +void gpgpu_sim::fq_pop(int tpc_id) { - int tid, nthreads_2beissued, more_threads; - int nthreads_in_block= 0; - int start_thread = 0; - int end_thread = shdr->n_threads; - int cta_id=-1; - int cta_size=0; - int padded_cta_size; + mem_fetch *mf = (mem_fetch*) icnt_pop(tpc_id); + if (!mf) + return; + assert(mf->type == REPLY_DATA); + if( mf->mshr && mf->mshr->has_inst() ) + time_vector_update(mf->mshr->get_insts_uid() ,MR_2SH_FQ_POP,gpu_sim_cycle+gpu_tot_sim_cycle, mf->type ); + if (mf->m_write) { + m_sc[mf->sid]->store_ack(mf); + delete mf; + } else { + m_memory_stats->memlatstat_read_done(mf,m_shader_config->max_warps_per_shader); + m_sc[mf->sid]->fill_shd_L1_with_new_line(mf); + } +} - cta_size = ptx_sim_cta_size(); - padded_cta_size = cta_size; +//////////////////////////////////////////////////////////////////////////////////////////////// - assert(gpgpu_spread_blocks_across_cores); //should be if muliple CTA per shader supported +/** + * Launches a cooperative thread array (CTA). + * + * @param kernel + * object that tells us which kernel to ask for a CTA from + */ - for (unsigned i=0;i<max_cta_per_shader(shdr);i++ ) { //try to find next empty cta slot - if (shdr->cta_status[i]==0) { // - cta_id=i; +void shader_core_ctx::issue_block2core( kernel_info_t &kernel ) +{ + // find a free CTA context + unsigned free_cta_hw_id=(unsigned)-1; + unsigned max_concurrent_cta_this_kernel = max_cta(kernel.entry()); + assert( max_concurrent_cta_this_kernel <= MAX_CTA_PER_SHADER ); + for (unsigned i=0;i<max_concurrent_cta_this_kernel;i++ ) { + if( m_cta_status[i]==0 ) { + free_cta_hw_id=i; break; } - } - assert( cta_id!=-1);//must have found a CTA to run - if (padded_cta_size%warp_size) { - padded_cta_size = ((padded_cta_size/warp_size)+1)*(warp_size); - } - start_thread = cta_id * padded_cta_size; - end_thread = start_thread + cta_size; - shader_reinit(shdr,start_thread, end_thread); - - // issue threads in blocks (if it is specified) - warp_set_t warps; - for (int i = start_thread; i<end_thread; i++) { //setup the block - unsigned warp_id = i/warp_size; - shdr->thread[i].cta_id = cta_id; - nthreads_in_block += ptx_sim_init_thread(&shdr->thread[i].ptx_thd_info,shdr->sid,i,cta_size-(i-start_thread),shdr->n_threads/*cta_size*/,shdr,cta_id,warp_id); - warps.set( warp_id ); - } - shdr->allocate_barrier( cta_id, warps ); + } + assert( free_cta_hw_id!=(unsigned)-1 ); - shader_init_CTA(shdr, start_thread, end_thread); - nthreads_2beissued = nthreads_in_block; - shdr->cta_status[cta_id]+=nthreads_2beissued; - assert( nthreads_2beissued ); //we should have not reached this point if there is no more thread to - + // determine hardware threads and warps that will be used for this CTA + int cta_size = kernel.threads_per_cta(); - assert( (unsigned) nthreads_2beissued <= shdr->n_threads); //confirm threads to be issued is less than or equal to number of threads supported by microarchitecture + // hw warp id = hw thread id mod warp size, so we need to find a range + // of hardware thread ids corresponding to an integral number of hardware + // thread ids + int padded_cta_size = cta_size; + if (cta_size%m_config->warp_size) + padded_cta_size = ((cta_size/m_config->warp_size)+1)*(m_config->warp_size); + unsigned start_thread = free_cta_hw_id * padded_cta_size; + unsigned end_thread = start_thread + cta_size; - int n_cta_issued= nthreads_2beissued/cta_size ;//+ nthreads_2beissued%cta_size; - shdr->n_active_cta += n_cta_issued; - shader_CTA_count_log(shdr->sid, n_cta_issued); - g_total_cta_left-= n_cta_issued; + // reset the microarchitecture state of the selected hardware thread and warp contexts + reinit(start_thread, end_thread,false); + + // initalize scalar threads and determine which hardware warps they are allocated to + // bind functional simulation state of threads to hardware resources (simulation) + warp_set_t warps; + unsigned nthreads_in_block= 0; + 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); + 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 + m_cta_status[free_cta_hw_id]=nthreads_in_block; - more_threads = 1; - if (gpgpu_spread_blocks_across_cores) { - nthreads_2beissued += start_thread; - } - printf("GPGPU-Sim uArch: Shader %d initializing CTA #%d with hw tids from %d to %d @(%lld,%lld)", - shdr->sid, cta_id, start_thread, nthreads_2beissued, gpu_sim_cycle, gpu_tot_sim_cycle ); - printf(" shdr->not_completed = %d\n", shdr->not_completed); - - for (tid=start_thread;tid<nthreads_2beissued;tid++) { + // now that we know which warps are used in this CTA, we can allocate + // resources for use in CTA-wide barrier operations + allocate_barrier( free_cta_hw_id, warps ); - // reset complete flag for stream - shdr->not_completed += 1; - assert( shdr->warp[tid/warp_size].n_completed > 0 ); - assert( shdr->warp[tid/warp_size].n_completed <= warp_size); - shdr->warp[tid/warp_size].n_completed--; + // initialize the SIMT stacks and fetch hardware + init_warps(start_thread, end_thread); - // set avail4fetch flag to ready - shdr->thread[tid].avail4fetch = 1; - assert( shdr->warp[tid/warp_size].n_avail4fetch < warp_size ); - shdr->warp[tid/warp_size].n_avail4fetch++; - - g_nthreads_issued++; - } + m_n_active_cta++; + g_total_cta_left-=1; // used for exiting early from simulation - if (!nthreads_in_block) more_threads = 0; - return more_threads; //if there are no more threads to be issued, return 0 + shader_CTA_count_log(m_sid, 1); + + printf("GPGPU-Sim uArch: Shader %d initialized CTA #%d with hw tids from %d to %d @(%lld,%lld)", + m_sid, free_cta_hw_id, start_thread, start_thread+nthreads_in_block, gpu_sim_cycle, gpu_tot_sim_cycle ); + printf(" active threads = %d\n", get_not_completed() ); + } + /////////////////////////////////////////////////////////////////////////////////////////// // wrapper code to to create an illusion of a memory controller with L2 cache. -// -int mem_ctrl_full( int mc_id ) -{ - if (gpgpu_cache_dl2_opt) { - return L2c_full( dram[mc_id] ); - } else { - return( gpgpu_dram_sched_queue_size && dram_full(dram[mc_id]) ); - } -} //#define DEBUG_PARTIAL_WRITES -void mem_ctrl_push( int mc_id, mem_fetch_t* mf ) +void memory_partition_unit::push( mem_fetch* req, unsigned long long cycle ) { - dram[mc_id]->m_request_tracker.insert(mf); - if (gpgpu_cache_dl2_opt) { - L2c_push(dram[mc_id], mf); - } else { - addrdec_t tlx; - addrdec_tlx(mf->addr, &tlx); -#if 0 //old chunking no longer valid. - if (gpgpu_partial_write_mask && mf->write) { - assert( gpgpu_no_dl1 ); // gpgpu_partial_write_mask is not supported with caches for now - } -#endif //#if 0 //old chunking no longer valid - dram_push(dram[mc_id], - tlx.bk, tlx.row, tlx.col, - mf->nbytes_L1, mf->write, - mf->wid, mf->sid, mf->cache_hits_waiting, mf->addr, mf); - memlatstat_dram_access(mf, mc_id, tlx.bk); - if (mf->mshr) mshr_update_status(mf->mshr,IN_DRAM_REQ_QUEUE); - } + if (req) { + rop_delay_t r; + r.req = req; + r.ready_cycle = cycle + 115; // Add 115*4=460 delay cycles + m_rop.push(r); + } + if ( !m_rop.empty() && (cycle >= m_rop.front().ready_cycle) ) { + mem_fetch* mf = m_rop.front().req; + m_rop.pop(); + if (mf->type==RD_REQ) { + if ( mf->mshr && mf->mshr->has_inst() ) + time_vector_update(mf->mshr->get_insts_uid(),MR_DRAMQ,gpu_sim_cycle+gpu_tot_sim_cycle,mf->type ) ; + } else { + if ( mf->mshr && !mf->mshr->isinst() ) + time_vector_update(mf->request_uid ,MR_DRAMQ,gpu_sim_cycle+gpu_tot_sim_cycle,mf->type ) ; + } + m_stats->memlatstat_icnt2mem_pop(mf); + request_tracker_insert(mf); + if (m_config->gpgpu_cache_dl2_opt) { + if (m_config->gpgpu_l2_readoverwrite && mf->m_write) + cbtoL2writequeue->push(mf,gpu_sim_cycle); + else + cbtoL2queue->push(mf,gpu_sim_cycle); + m_accessLocality->access(mf); + if (mf->mshr) mf->mshr->set_status(IN_CBTOL2QUEUE); + } else { + m_dram->push(mf); + if (mf->mshr) mf->mshr->set_status(IN_DRAM_REQ_QUEUE); + } + } } -void* mem_ctrl_pop( int mc_id ) +mem_fetch* memory_partition_unit::pop() { - mem_fetch_t* mf; - if (gpgpu_cache_dl2_opt) { - mf = L2c_pop(dram[mc_id]); - if (mf && mf->mshr && mf->mshr->insts[0].callback.function) { - dram_callback_t* cb = &(mf->mshr->insts[0].callback); - cb->function(cb->instruction, cb->thread); + mem_fetch* mf; + if (m_config->gpgpu_cache_dl2_opt) { + mf = L2c_pop(m_dram); + if (mf && mf->mshr && mf->mshr->isatomic() ) { + dram_callback_t &cb = mf->mshr->get_atomic_callback(); + cb.function(cb.instruction, cb.thread); } - dram[mc_id]->m_request_tracker.erase(mf); - return mf; } else { - mf = static_cast<mem_fetch_t*> (dq_pop(dram[mc_id]->returnq)); //dram_pop(dram[mc_id]); + mf = m_dram->returnq_pop(gpu_sim_cycle); if (mf) mf->type = REPLY_DATA; - if (mf && mf->mshr && mf->mshr->insts[0].callback.function) { - dram_callback_t* cb = &(mf->mshr->insts[0].callback); - cb->function(cb->instruction, cb->thread); + if (mf && mf->mshr && mf->mshr->isatomic() ) { + dram_callback_t &cb = mf->mshr->get_atomic_callback(); + cb.function(cb.instruction, cb.thread); } - dram[mc_id]->m_request_tracker.erase(mf); - return mf; } + request_tracker_erase(mf); + return mf; } -void* mem_ctrl_top( int mc_id ) +mem_fetch* memory_partition_unit::top() { - mem_fetch_t* mf; - if (gpgpu_cache_dl2_opt) { - return L2c_top(dram[mc_id]); + if (m_config->gpgpu_cache_dl2_opt) { + return L2tocbqueue->top(); } else { - mf = static_cast<mem_fetch_t*> (dq_top(dram[mc_id]->returnq));//dram_top(dram[mc_id]); + mem_fetch* mf = m_dram->returnq_top(); if (mf) mf->type = REPLY_DATA; - return mf ;//dram_top(dram[mc_id]); + return mf; } } -void get_dram_output ( dram_t* dram_p ) -{ - mem_fetch_t* mf; - mem_fetch_t* mf_top; - mf_top = (mem_fetch_t*) dram_top(dram_p); //test +void memory_partition_unit::issueCMD() +{ + mem_fetch* mf_top = m_dram->top(); if (mf_top) { if (mf_top->type == DUMMY_READ) { - dram_pop(dram_p); + m_dram->pop(); free(mf_top); freed_dummy_read_mfs++; return; } } - if (gpgpu_cache_dl2_opt) { - L2c_get_dram_output( dram_p ); + if (m_config->gpgpu_cache_dl2_opt) { + L2c_get_dram_output(); } else { - if ( dq_full(dram_p->returnq) ) return; - mf = (mem_fetch_t*) dram_pop(dram_p); + if ( m_dram->returnq_full() ) + return; + mem_fetch* mf = m_dram->pop(); assert (mf_top==mf ); if (mf) { - dq_push(dram_p->returnq, mf); - if (mf->mshr) mshr_update_status(mf->mshr,IN_DRAMRETURN_Q); + m_dram->returnq_push(mf,gpu_sim_cycle); + if (mf->mshr) mf->mshr->set_status(IN_DRAMRETURN_Q); } } + m_dram->issueCMD(); + m_dram->dram_log(SAMPLELOG); } -void dram_log (int task ) { - static void ** mrqq_Dist; //memory request queue inside DRAM - if (task == CREATELOG) { - mrqq_Dist = (void **) calloc(gpu_n_mem,sizeof(void*)); - for (unsigned i=0;i<gpu_n_mem;i++) { - if (dram[i]->queue_limit) - mrqq_Dist[i] = StatCreate("mrqq_length",1,dram[i]->queue_limit); - else //queue length is unlimited; - mrqq_Dist[i] = StatCreate("mrqq_length",1,64); //track up to 64 entries - } - } else if (task == SAMPLELOG) { - for (unsigned i=0;i<gpu_n_mem;i++) { - StatAddSample(mrqq_Dist[i], dram_que_length(dram[i])); - } - } else if (task == DUMPLOG) { - for (unsigned i=0;i<gpu_n_mem;i++) { - printf ("Queue Length DRAM[%d] ",i);StatDisp(mrqq_Dist[i]); - } - } -} - -void dramqueue_latency_log_dump() +void dram_t::dram_log( int task ) { - for (unsigned i=0;i<gpu_n_mem;i++) { - printf ("(LOGB2)Latency DRAM[%d] ",i);StatDisp(dram[i]->mrqq->lat_stat); - printf ("(LOGB2)Latency DRAM[%d] ",i);StatDisp(dram[i]->rwq->lat_stat); + if (task == SAMPLELOG) { + StatAddSample(mrqq_Dist, que_length()); + } else if (task == DUMPLOG) { + printf ("Queue Length DRAM[%d] ",id);StatDisp(mrqq_Dist); } } //Find next clock domain and increment its time -inline int next_clock_domain(void) +int gpgpu_sim::next_clock_domain(void) { double smallest = min3(core_time,icnt_time,dram_time); int mask = 0x00; - if (gpgpu_cache_dl2_opt //when no-L2 it will never be L2's turn + if (m_memory_config->gpgpu_cache_dl2_opt //when no-L2 it will never be L2's turn && ( l2_time <= smallest) ) { smallest = l2_time; mask |= L2 ; @@ -1411,181 +1318,114 @@ inline int next_clock_domain(void) return mask; } -void gpu_sim_loop( int grid_num ) +unsigned long long g_single_step=0; // set this in gdb to single step the pipeline + +void gpgpu_sim::gpu_sim_loop() { 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++) { + for (int i=0;i<gpu_n_tpc;i++) fq_pop(i); - } } - if (clock_mask & ICNT) { - // pop from memory controller to interconnect - static unsigned int *rt_size = NULL; - if (!rt_size) rt_size = (unsigned int*) malloc ((gpu_n_tpc+gpu_n_mem)*sizeof(unsigned int)); - memset(rt_size, 0, (gpu_n_tpc+gpu_n_mem)*sizeof(unsigned int)); - - for (unsigned i=0;i<gpu_n_mem;i++) { - - mem_fetch_t* mf; - - mf = (mem_fetch_t*) mem_ctrl_top(i); //(returns L2_top or DRAM returnq top) - - if (mf) { - mf->source_node = mem2device(i); - assert( mf->type != RD_REQ && mf->type != WT_REQ ); // never should a request come out from L2 or dram - if (!mf->write) { - int return_dev = -1; - return_dev = mf->sid / gpu_concentration; - assert(return_dev != -1); - // check icnt resource for READ data return - rt_size[return_dev] = mf->nbytes_L1; - if ( icnt_has_buffer( mem2device(i), rt_size) ) { - if (mf->mshr) mshr_update_status(mf->mshr,IN_ICNT2SHADER); - memlatstat_icnt2sh_push(mf); - time_vector_update(mf->mshr->insts[0].uid ,MR_2SH_ICNT_PUSHED,gpu_sim_cycle+gpu_tot_sim_cycle,RD_REQ); - icnt_push( mem2device(i), return_dev, mf, mf->nbytes_L1); - mem_ctrl_pop(i); - } else { - gpu_stall_icnt2sh++; - } - rt_size[return_dev] = 0; // clean up for the next dram_pop - } else { - time_vector_update(mf->request_uid ,MR_2SH_ICNT_PUSHED,gpu_sim_cycle+gpu_tot_sim_cycle,WT_REQ ) ; - mem_ctrl_pop(i); - free(mf); - freed_L1write_mfs++; - gpgpu_n_processed_writes++; + if (clock_mask & ICNT) { + // pop from memory controller to interconnect + for (unsigned i=0;i<m_n_mem;i++) { + mem_fetch* mf = m_memory_partition_unit[i]->top(); + if (mf) { + assert( mf->type != RD_REQ && mf->type != WT_REQ ); + unsigned response_size = mf->m_write?mf->nbytes_L1:WRITE_PACKET_SIZE; + if ( icnt_has_buffer( mem2device(i), response_size ) ) { + if (!mf->m_write) { + if (mf->mshr) mf->mshr->set_status(IN_ICNT2SHADER); + m_memory_stats->memlatstat_icnt2sh_push(mf); + if ( mf->mshr && mf->mshr->has_inst() ) + time_vector_update(mf->mshr->get_insts_uid(),MR_2SH_ICNT_PUSHED,gpu_sim_cycle+gpu_tot_sim_cycle,RD_REQ); + } else { + time_vector_update(mf->request_uid ,MR_2SH_ICNT_PUSHED,gpu_sim_cycle+gpu_tot_sim_cycle,WT_REQ ) ; + freed_L1write_mfs++; + gpgpu_n_processed_writes++; + } + int return_dev = mf->sid / gpu_concentration; + icnt_push( mem2device(i), return_dev, mf, response_size ); + m_memory_partition_unit[i]->pop(); + } else { + gpu_stall_icnt2sh++; + } } - } - } - } + } + } if (clock_mask & DRAM) { - for (unsigned i=0;i<gpu_n_mem;i++) { - get_dram_output ( dram[i] ); - } - // Issue the dram command (scheduler + delay model) - for (unsigned i=0;i<gpu_n_mem;i++) { - dram_issueCMD(dram[i]); + for (unsigned i=0;i<m_n_mem;i++) { + m_memory_partition_unit[i]->issueCMD(); // Issue the dram command (scheduler + delay model) } - dram_log(SAMPLELOG); } // L2 operations follow L2 clock domain if (clock_mask & L2) { - for (unsigned i=0;i<gpu_n_mem;i++) { - L2c_process_dram_output ( dram[i], i ); // pop from dram - L2c_push_miss_to_dram ( dram[i] ); //push to dram - L2c_service_mem_req ( dram[i], i ); // pop(push) from(to) icnt2l2(l2toicnt) queues; service l2 requests - } - if (gpgpu_cache_dl2_opt) { // L2 cache enabled - for (unsigned i=0;i<gpu_n_mem;i++) { - L2c_update_stat( dram[i] ); - } - } - if (gpgpu_cache_dl2_opt) { //take a sample of l2c queue lengths - L2c_log(SAMPLELOG); - } + for (unsigned i=0;i<m_n_mem;i++) + m_memory_partition_unit[i]->cache_cycle(); } if (clock_mask & ICNT) { - // pop memory request from ICNT and - // push it to a dram delay queue - for (unsigned i=0;i<gpu_n_mem;i++) { - // Push memory request to dram delay queue if mem_ctrl is not full - if ( mem_ctrl_full(i) ) { + for (unsigned i=0;i<m_n_mem;i++) { + if ( m_memory_partition_unit[i]->full() ) { + gpu_stall_dramfull++; continue; } - - mem_fetch_t* mf; - mf = (mem_fetch_t*) icnt_pop( mem2device(i) ); - - if (mf) { - - dram_delay_t dram_delay; - dram_delay.mf = mf; - dram_delay.ready_cycle = gpu_sim_cycle + gpu_tot_sim_cycle + 115; // Add 115*4=460 delay cycles - dram_delay_queues[i].push(dram_delay); - } - } - - // pop memory request from dram delay queue and - // push it to the proper memory controller (L2 or DRAM controller) - for (unsigned i=0;i<gpu_n_mem;i++) { - if(!dram_delay_queues[i].empty() && dram_delay_queues[i].front().ready_cycle <= gpu_sim_cycle + gpu_tot_sim_cycle) { - if ( mem_ctrl_full(i) ) { - gpu_stall_dramfull++; - continue; - } - mem_fetch_t* mf = dram_delay_queues[i].front().mf; - if (mf->type==RD_REQ) { - time_vector_update(mf->mshr->insts[0].uid ,MR_DRAMQ,gpu_sim_cycle+gpu_tot_sim_cycle,mf->type ) ; - } else { - time_vector_update(mf->request_uid ,MR_DRAMQ,gpu_sim_cycle+gpu_tot_sim_cycle,mf->type ) ; - } - memlatstat_icnt2mem_pop(mf); - mem_ctrl_push( i, mf ); - - dram_delay_queues[i].pop(); - } + // move memory request from interconnect into memory partition (if memory controller not backed up) + mem_fetch* mf = (mem_fetch*) icnt_pop( mem2device(i) ); + m_memory_partition_unit[i]->push( mf, gpu_sim_cycle + gpu_tot_sim_cycle ); } - - icnt_transfer( ); + icnt_transfer(); } if (clock_mask & CORE) { // L1 cache + shader core pipeline stages - for (unsigned i=0;i<gpu_n_shader;i++) { - if (sc[i]->not_completed || more_thread) - shader_cycle(sc[i], i, grid_num); - sc[i]->gpu_cycle++; + for (unsigned i=0;i<m_n_shader;i++) { + if (m_sc[i]->get_not_completed() || more_thread) { + if (!strcmp("GPGPUSIM_ORIG",m_shader_config->pipeline_model) ) + m_sc[i]->cycle(); + else if (!strcmp("GT200",m_shader_config->pipeline_model) ) + m_sc[i]->cycle_gt200(); + } + } + if( g_single_step && ((gpu_sim_cycle+gpu_tot_sim_cycle) >= g_single_step) ) { + asm("int $03"); } gpu_sim_cycle++; if( g_interactive_debugger_enabled ) gpgpu_debug(); - for (unsigned i=0;i<gpu_n_shader && more_thread;i++) { - if (gpgpu_spread_blocks_across_cores) { - int cta_issue_count = 1; - if ( ( (unsigned) (sc[i]->n_active_cta + cta_issue_count) <= max_cta_per_shader(sc[i]) ) - && g_total_cta_left ) { - int j; - for (j=0;j<cta_issue_count;j++) { - issue_block2core(sc[i], grid_num); - } - if (!g_total_cta_left) { - more_thread = 0; - } - assert( g_total_cta_left > -1 ); - } - } else { - if (!(sc[i]->not_completed)) - more_thread = issue_block2core(sc[i], grid_num); + 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 ); + if (!g_total_cta_left) + more_thread = 0; + assert( g_total_cta_left > -1 ); } } - // Flush the caches once all of threads are completed. if (gpgpu_flush_cache) { int all_threads_complete = 1 ; - for (unsigned i=0;i<gpu_n_shader;i++) { - if (sc[i]->not_completed == 0) { - shader_cache_flush(sc[i]); + for (unsigned i=0;i<m_n_shader;i++) { + if (m_sc[i]->get_not_completed() == 0) { + m_sc[i]->cache_flush(); } else { all_threads_complete = 0 ; } } if (all_threads_complete) { printf("Flushed L1 caches...\n"); - if (gpgpu_cache_dl2_opt) { + if (m_memory_config->gpgpu_cache_dl2_opt) { int dlc = 0; - for (unsigned i=0;i<gpu_n_mem;i++) { - dlc = L2c_cache_flush(dram[i]); - printf("Dirty lines flushed from L2 %d is %d \n", i, dlc ); + for (unsigned i=0;i<m_n_mem;i++) { + dlc = m_memory_partition_unit[i]->L2c_cache_flush(); + printf("Dirty lines flushed from L2 %d is %d\n", i, dlc ); } } } @@ -1607,23 +1447,22 @@ void gpu_sim_loop( int grid_num ) (unsigned)days,(unsigned)hrs,(unsigned)minutes,(unsigned)sec, ctime(&curr_time)); fflush(stdout); - memlatstat_lat_pw(); + m_memory_stats->memlatstat_lat_pw(m_n_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<gpu_n_mem;i++) { - dram_print_stat(dram[i],stdout); - } - printf("maxmrqlatency = %d \n", max_mrq_latency); - printf("maxmflatency = %d \n", max_mf_latency); + for (unsigned i=0;i<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); } if (gpu_runtime_stat_flag & GPU_RSTAT_DWF_MAP) { printf("DWF_MS: "); - for (unsigned i=0;i<gpu_n_shader;i++) { + for (unsigned i=0;i<m_n_shader;i++) { printf("%u ",acc_dyn_pcs[i]); } printf("\n"); - print_thread_pc( stdout ); + print_thread_pc( stdout, m_n_shader ); } if (gpu_runtime_stat_flag & GPU_RSTAT_SHD_INFO) { shader_print_runtime_stat( stdout ); @@ -1635,25 +1474,24 @@ void gpu_sim_loop( int grid_num ) shader_print_l1_miss_stat( stdout ); } if (gpu_runtime_stat_flag & GPU_RSTAT_PDOM ) { - if (pdom_sched_type) { - printf ("pdom_original_warps_count %d \n",n_pdom_sc_orig_stat ); - printf ("pdom_single_warps_count %d \n",n_pdom_sc_single_stat ); + if (m_pdom_sched_type) { + printf ("pdom_original_warps_count %d \n",m_shader_stats->n_pdom_sc_orig_stat ); + printf ("pdom_single_warps_count %d \n",m_shader_stats->n_pdom_sc_single_stat ); } } if (gpu_runtime_stat_flag & GPU_RSTAT_SCHED ) { printf("Average Num. Warps Issuable per Shader:\n"); - for (unsigned i=0;i<gpu_n_shader;i++) { - printf("%2.2f ", (float) num_warps_issuable_pershader[i]/ gpu_stat_sample_freq); - num_warps_issuable_pershader[i] = 0; + for (unsigned i=0;i<m_n_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; } printf("\n"); } } } - for (unsigned i=0;i<gpu_n_mem;i++) { - acc_mrq_length[i] += dram_que_length(dram[i]); - } + for (unsigned i=0;i<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 if (gpu_deadlock_detect && gpu_sim_insn == last_gpu_sim_insn) { @@ -1667,56 +1505,21 @@ void gpu_sim_loop( int grid_num ) } } -void dump_regs(unsigned sid, unsigned tid) +void shader_core_ctx::dump_istream_state( FILE *fout ) { - if ( sid >= gpu_n_shader ) { - printf("shader %u is out of range\n",sid); - return; - } - if ( tid >= gpu_n_thread_per_shader ) { - printf("thread %u is out of range\n",tid); - return; - } - - shader_core_ctx_t *s = sc[sid]; - - ptx_dump_regs( s->thread[tid].ptx_thd_info ); + fprintf(fout, "\n"); + for (unsigned w=0; w < m_config->max_warps_per_shader; w++ ) + m_warp[w].print(fout); } -void shader_dump_istream_state(shader_core_ctx_t *shader, FILE *fout ) -{ - fprintf( fout, "\n"); - for (unsigned t=0; t < gpu_n_thread_per_shader/warp_size; t++ ) { - int tid = t*warp_size; - if ( shader->warp[t].n_completed < warp_size ) { - fprintf( fout, " %u:%3u (w%02u) fetch state = c:%u a4f:%u bw:%u (completed: ", shader->sid, tid, t, - shader->warp[t].n_completed, - shader->warp[t].n_avail4fetch, - shader->warp[t].n_waiting_at_barrier ); - - for (unsigned i = tid; i < (t+1)*warp_size; i++ ) { - if ( ptx_thread_done(shader->thread[i].ptx_thd_info) ) { - fprintf(fout,"1"); - } else { - fprintf(fout,"0"); - } - if ( (((i+1)%4) == 0) && (i+1) < (t+1)*warp_size ) { - fprintf(fout,","); - } - } - fprintf(fout,")\n"); - } - } -} - -void dump_pipeline_impl( int mask, int s, int m ) +void gpgpu_sim::dump_pipeline( int mask, int s, int m ) const { /* You may want to use this function while running GPGPU-Sim in gdb. One way to do that is add the following to your .gdbinit file: define dp - call dump_pipeline_impl((0x40|0x4|0x1),$arg0,0) + call g_the_gpu.dump_pipeline_impl((0x40|0x4|0x1),$arg0,0) end Then, typing "dp 3" will show the contents of the pipeline for shader core 3. @@ -1724,25 +1527,26 @@ void dump_pipeline_impl( int mask, int s, int m ) printf("Dumping pipeline state...\n"); if(!mask) mask = 0xFFFFFFFF; - for (unsigned i=0;i<gpu_n_shader;i++) { + for (unsigned i=0;i<m_n_shader;i++) { if(s != -1) { i = s; } - if(mask&1) shader_display_pipeline(sc[i], stdout, 1, mask & 0x2E ); - if(mask&0x40) shader_dump_istream_state(sc[i], stdout); - if(mask&0x100) mshr_print(stdout, sc[i]); + if(mask&1) m_sc[i]->display_pipeline(stdout, 1, mask & 0x2E ); + if (!strcmp("GPGPUSIM_ORIG",m_shader_config->pipeline_model) ) + if(mask&0x40) m_sc[i]->dump_istream_state(stdout); + if(mask&0x100) m_sc[i]->mshr_print(stdout, mask); if(s != -1) { break; } } if(mask&0x10000) { - for (unsigned i=0;i<gpu_n_mem;i++) { + for (unsigned i=0;i<m_n_mem;i++) { if(m != -1) { i=m; } printf("DRAM / memory controller %u:\n", i); - if(mask&0x100000) dram_print_stat(dram[i],stdout); - if(mask&0x1000000) dram_visualize( dram[i] ); + if(mask&0x100000) m_memory_partition_unit[i]->print_stat(stdout); + if(mask&0x1000000) m_memory_partition_unit[i]->visualize(); if(m != -1) { break; } @@ -1751,8 +1555,7 @@ void dump_pipeline_impl( int mask, int s, int m ) fflush(stdout); } -void dump_pipeline() +void memory_partition_unit::visualizer_print( gzFile visualizer_file ) { - dump_pipeline_impl(0,-1,-1); + m_dram->visualizer_print(visualizer_file); } - |
