summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/gpu-sim.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpgpu-sim/gpu-sim.cc')
-rw-r--r--src/gpgpu-sim/gpu-sim.cc1583
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);
}
-