From b577cbcdf229a2c02d1bf8584c6e82be7a14cb33 Mon Sep 17 00:00:00 2001 From: Tor Aamodt Date: Sat, 16 Oct 2010 17:30:52 -0800 Subject: 1. creating cache_config object to encapsulate cache configuration information (and parse it before creating the simulator objects). 2. creating core_config to hold only features of a shader_core that are high level enough either (a) the functional simulator needs to know about them, or (b) they affect memory *access* generation. 3. in config files only (so far) separate out notion of write-{through,back}, from notion of when a line is allocated... will use this to distinguish different types of caches. passing CUDA 3.1 regression [git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7870] --- src/gpgpu-sim/gpu-cache.cc | 39 ++------ src/gpgpu-sim/gpu-cache.h | 78 ++++++++++++--- src/gpgpu-sim/gpu-sim.cc | 55 +++++------ src/gpgpu-sim/gpu-sim.h | 10 +- src/gpgpu-sim/l2cache.cc | 23 ++--- src/gpgpu-sim/shader.cc | 236 ++++++++------------------------------------- src/gpgpu-sim/shader.h | 95 +++++++++++++----- src/gpgpu-sim/stats.h | 2 +- 8 files changed, 238 insertions(+), 300 deletions(-) (limited to 'src/gpgpu-sim') diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index c1acc83..98909ce 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -77,39 +77,20 @@ cache_t::~cache_t() delete m_lines; } -cache_t::cache_t( const char *name, - const char *opt, - enum cache_write_policy wp, - int core_id, - int type_id ) +cache_t::cache_t( const char *name, const cache_config &config, int core_id, int type_id ) + : m_config(config) { - unsigned int nset; - unsigned int line_sz; - unsigned int assoc; - unsigned char policy; - int ntok = sscanf(opt,"%d:%d:%d:%c", &nset, &line_sz, &assoc, &policy); - if( ntok != 4 ) { - printf("GPGPU-Sim uArch: cache configuration string parsing error for cache %s\n", name); - abort(); - } - assert(nset && assoc); - - unsigned int nlines; - nlines = nset * assoc; m_name = name; - m_nset = nset; - m_nset_log2 = LOGB2(nset); - m_assoc = assoc; - m_line_sz = line_sz; - m_line_sz_log2 = LOGB2(line_sz); - m_replacement_policy = policy; - m_write_policy = wp; + m_nset = config.nset; + m_nset_log2 = LOGB2(config.nset); + m_assoc = config.assoc; + m_line_sz = config.line_sz; + m_line_sz_log2 = LOGB2(config.line_sz); + m_replacement_policy = config.replacement_policy; + m_write_policy = config.get_write_policy(); + unsigned nlines = config.get_num_lines(); m_lines = new cache_block_t[nlines]; - // don't hook up with any logger - m_core_id = -1; - m_type_id = -1; - // initialize snapshot counters for visualizer m_prev_snapshot_access = 0; m_prev_snapshot_miss = 0; diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 21cdbbc..89a2ed0 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -101,23 +101,79 @@ struct cache_block_t { unsigned char status; /* valid, dirty... etc */ }; -#define LRU 'L' -#define FIFO 'F' -#define RANDOM 'R' +enum replacement_policy { + LRU, + FIFO +}; -enum cache_write_policy { +enum write_policy { no_writes, // line replacement when new line arrives write_back, // line replacement when new line arrives write_through // reservation based, use much handle reservation full error. }; +enum allocation_policy { + on_miss, + on_fill +}; + +class cache_config { +public: + cache_config() + { + m_valid = false; + m_config_string = NULL; // set by option parser + } + void init() + { + assert( m_config_string ); + int ntok = sscanf(m_config_string,"%d:%d:%d:%c:%c:%c", &nset, &line_sz, &assoc, &replacement_policy, &write_policy, &alloc_policy); + if( ntok != 6 ) { + printf("GPGPU-Sim uArch: cache configuration parsing error (%s)\n", m_config_string ); + abort(); + } + m_valid = true; + } + unsigned get_line_sz() const + { + assert( m_valid ); + return line_sz; + } + unsigned get_num_lines() const + { + assert( m_valid ); + return nset * assoc; + } + + enum write_policy get_write_policy() const + { + if( write_policy == 'R' ) + return no_writes; + else if( write_policy == 'B' ) + return write_back; + else if( write_policy == 'T' ) + return write_through; + else + abort(); + } + + char *m_config_string; + +private: + bool m_valid; + unsigned int nset; + unsigned int line_sz; + unsigned int assoc; + unsigned char replacement_policy; // 'L' = LRU, 'F' = FIFO, 'R' = RANDOM + unsigned char write_policy; // 'T' = write through, 'B' = write back, 'R' = read only + unsigned char alloc_policy; // 'm' = allocate on miss, 'f' = allocate on fill + + friend class cache_t; +}; + class cache_t { public: - cache_t( const char *name, - const char *opt, - enum cache_write_policy wp, - int core_id, - int type_id); + cache_t( const char *name, const cache_config &config, int core_id, int type_id ); ~cache_t(); enum cache_request_status access( new_addr_type addr, @@ -132,10 +188,10 @@ public: void print( FILE *stream, unsigned &total_access, unsigned &total_misses ); float windowed_cache_miss_rate(int); void new_window(); - unsigned get_line_sz() const { return m_line_sz; } private: std::string m_name; + const cache_config &m_config; cache_block_t *m_lines; /* nbanks x nset x assoc lines in total */ unsigned m_n_banks; @@ -145,7 +201,7 @@ private: unsigned m_line_sz; // bytes unsigned m_line_sz_log2; - enum cache_write_policy m_write_policy; + enum write_policy m_write_policy; unsigned char m_replacement_policy; unsigned m_access; diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index dc4241b..b3bc56a 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -169,27 +169,27 @@ void gpgpu_sim::reg_options(option_parser_t opp) "terminates gpu simulation early (0 = no limit)", "0"); - option_parser_register(opp, "-gpgpu_tex_cache:l1", OPT_CSTR, &m_shader_config->gpgpu_cache_texl1_opt, + option_parser_register(opp, "-gpgpu_tex_cache:l1", OPT_CSTR, &m_shader_config->m_L1T_config.m_config_string, "per-shader L1 texture cache (READ-ONLY) config, i.e., {:::|none}", - "512:64:2:L"); + "512:64:2:L:R:m"); - option_parser_register(opp, "-gpgpu_const_cache:l1", OPT_CSTR, &m_shader_config->gpgpu_cache_constl1_opt, + option_parser_register(opp, "-gpgpu_const_cache:l1", OPT_CSTR, &m_shader_config->m_L1C_config.m_config_string, "per-shader L1 constant memory cache (READ-ONLY) config, i.e., {:::|none}", - "64:64:2:L"); + "64:64:2:L:R:f"); 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, &m_shader_config->gpgpu_cache_dl1_opt, + option_parser_register(opp, "-gpgpu_cache:dl1", OPT_CSTR, &m_shader_config->m_L1D_config.m_config_string, "shader L1 data cache config, i.e., {:::|none}", "256:128:1:L"); - option_parser_register(opp, "-gpgpu_cache:il1", OPT_CSTR, &m_shader_config->gpgpu_cache_il1_opt, + option_parser_register(opp, "-gpgpu_cache:il1", OPT_CSTR, &m_shader_config->m_L1I_config.m_config_string, "shader L1 instruction cache config, i.e., {:::|none}", - "4:256:4:L"); + "4:256:4:L:R:f"); - option_parser_register(opp, "-gpgpu_cache:dl2", OPT_CSTR, &m_memory_config->gpgpu_cache_dl2_opt, + option_parser_register(opp, "-gpgpu_cache:dl2", OPT_CSTR, &m_memory_config->m_L2_config.m_config_string, "unified banked L2 data cache config, i.e., {:::|none}; disabled by default", NULL); @@ -275,10 +275,6 @@ void gpgpu_sim::reg_options(option_parser_t opp) "Number of groups each warp is divided for shared memory bank conflict check", "2"); - 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"); - option_parser_register(opp, "-gpgpu_deadlock_detect", OPT_BOOL, &gpu_deadlock_detect, "Stop the simulation at deadlock (1=on (default), 0=off)", "1"); @@ -416,9 +412,9 @@ void gpgpu_sim::next_grid() gpgpu_sim::gpgpu_sim() { m_options_set=false; - 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_shader_config = new shader_core_config(); + m_memory_config = new memory_config(); + m_shader_stats = (shader_core_stats*) calloc(1,sizeof(shader_core_stats)); m_memory_stats = NULL; gpu_sim_insn = 0; gpu_tot_sim_insn = 0; @@ -427,7 +423,7 @@ gpgpu_sim::gpgpu_sim() gpu_deadlock = false; } -void set_ptx_warp_size(const struct shader_core_config * warp_size); +void set_ptx_warp_size(const struct core_config * warp_size); void gpgpu_sim::init_gpu() { @@ -440,9 +436,8 @@ void gpgpu_sim::init_gpu() &m_shader_config->n_thread_per_shader, &m_shader_config->warp_size); set_ptx_warp_size(m_shader_config); - - 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_config->init(); 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_shader_config->n_simt_clusters*m_shader_config->n_simt_cores_per_cluster, sizeof(int)); @@ -645,7 +640,7 @@ unsigned int gpgpu_sim::run_gpu_sim() if (m_memory_config->gpgpu_memlatency_stat & GPU_MEMLATSTAT_QUEUELOGS ) { for (unsigned i=0;im_n_mem;i++) m_memory_partition_unit[i]->queue_latency_log_dump(stdout); - if (m_memory_config->gpgpu_cache_dl2_opt) { + if (m_memory_config->m_L2_config.get_num_lines() > 0 ) { for(unsigned i=0; im_n_mem; i++) m_memory_partition_unit[i]->L2c_log(DUMPLOG); L2c_latency_log_dump(); @@ -732,9 +727,9 @@ void gpgpu_sim::gpu_print_stat() const //for (unsigned i=0; i< m_n_shader; i++) printf("%d ", m_sc[i]->get_max_mshr_used() ); //printf("\n"); - if (m_memory_config->gpgpu_cache_dl2_opt) { + if (m_memory_config->m_L2_config.get_num_lines()) m_memory_stats->L2c_print_stat( m_memory_config->m_n_mem ); - } + for (unsigned i=0;im_n_mem;i++) m_memory_partition_unit[i]->print(stdout); /* @@ -749,7 +744,7 @@ void gpgpu_sim::gpu_print_stat() const m_sc[i]->L1constcache_print(stdout,a,m); printf("L1 Const Cache Total Miss Rate = %0.3f\n", (float)m/a); */ - if (m_memory_config->gpgpu_cache_dl2_opt) + if (m_memory_config->m_L2_config.get_num_lines()) L2c_print_cache_stat(); if (m_shader_config->model == POST_DOMINATOR) { @@ -956,7 +951,7 @@ void memory_partition_unit::push( mem_fetch* req, unsigned long long cycle ) mem_fetch* mf = m_rop.front().req; m_rop.pop(); m_stats->memlatstat_icnt2mem_pop(mf); - if (m_config->gpgpu_cache_dl2_opt) { + if (m_config->m_L2_config.get_num_lines()) { if (m_config->gpgpu_l2_readoverwrite && mf->get_is_write()) m_icnt2cache_write_queue->push(mf,gpu_sim_cycle); else @@ -973,7 +968,7 @@ void memory_partition_unit::push( mem_fetch* req, unsigned long long cycle ) mem_fetch* memory_partition_unit::pop() { mem_fetch* mf; - if( m_config->gpgpu_cache_dl2_opt ) { + if( m_config->m_L2_config.get_num_lines()) { mf = L2tocbqueue->pop(gpu_sim_cycle); if( mf && mf->isatomic() ) mf->do_atomic(); @@ -991,7 +986,7 @@ mem_fetch* memory_partition_unit::pop() mem_fetch* memory_partition_unit::top() { - if (m_config->gpgpu_cache_dl2_opt) { + if (m_config->m_L2_config.get_num_lines()) { return L2tocbqueue->top(); } else { mem_fetch* mf = m_dram->returnq_top(); @@ -1002,7 +997,7 @@ mem_fetch* memory_partition_unit::top() void memory_partition_unit::issueCMD() { - if (m_config->gpgpu_cache_dl2_opt) { + if (m_config->m_L2_config.get_num_lines()) { // pop completed memory request from dram and push it to dram-to-L2 queue if ( !(dramtoL2queue->full() || dramtoL2writequeue->full()) ) { mem_fetch* mf = m_dram->pop(); @@ -1046,8 +1041,8 @@ int gpgpu_sim::next_clock_domain(void) { double smallest = min3(core_time,icnt_time,dram_time); int mask = 0x00; - if (m_memory_config->gpgpu_cache_dl2_opt //when no-L2 it will never be L2's turn - && ( l2_time <= smallest) ) { + if ( m_memory_config->m_L2_config.get_num_lines() //when no-L2 it will never be L2's turn + && (l2_time <= smallest) ) { smallest = l2_time; mask |= L2 ; l2_time += l2_period; @@ -1157,7 +1152,7 @@ void gpgpu_sim::cycle() } if (all_threads_complete) { printf("Flushed L2 caches...\n"); - if (m_memory_config->gpgpu_cache_dl2_opt) { + if (m_memory_config->m_L2_config.get_num_lines()) { int dlc = 0; for (unsigned i=0;im_n_mem;i++) { dlc = m_memory_partition_unit[i]->flushL2(); diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h index 762cea2..b881806 100644 --- a/src/gpgpu-sim/gpu-sim.h +++ b/src/gpgpu-sim/gpu-sim.h @@ -71,6 +71,8 @@ #include "../abstract_hardware_model.h" #include "addrdec.h" +#include "gpu-cache.h" +#include "shader.h" #include #include @@ -106,7 +108,7 @@ enum dram_ctrl_t { struct memory_config { memory_config() { - gpgpu_cache_dl2_opt=NULL; + m_valid = false; gpgpu_dram_timing_opt=NULL; gpgpu_L2_queue_config=NULL; } @@ -117,9 +119,13 @@ struct memory_config { tRCDWR = tRCD-(WL+1); tRTW = (CL+(BL/2)+2-WL); m_address_mapping.init(m_n_mem); + m_L2_config.init(); + m_valid = true; } - char *gpgpu_cache_dl2_opt; + bool m_valid; + cache_config m_L2_config; + char *gpgpu_dram_timing_opt; char *gpgpu_L2_queue_config; bool gpgpu_l2_readoverwrite; diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index 4c77da4..d2b61d7 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -286,7 +286,7 @@ void memory_partition_unit::cache_cycle() process_dram_output(); // pop from dram L2c_push_miss_to_dram(); // push to dram L2c_service_mem_req(); // pop(push) from(to) icnt2l2(l2toicnt) queues; service l2 requests - if (m_config->gpgpu_cache_dl2_opt) { // L2 cache enabled + if (m_config->m_L2_config.get_num_lines()) { // L2 cache enabled L2c_update_stat(); L2c_log(SAMPLELOG); } @@ -294,12 +294,12 @@ void memory_partition_unit::cache_cycle() unsigned memory_partition_unit::L2c_get_linesize() { - return m_L2cache->get_line_sz(); + return m_config->m_L2_config.get_line_sz(); } bool memory_partition_unit::full() const { - if (m_config->gpgpu_cache_dl2_opt) { + if (m_config->m_L2_config.get_num_lines()) { return m_icnt2cache_queue->full() || m_icnt2cache_write_queue->full(); } else { return( m_config->gpgpu_dram_sched_queue_size && m_dram->full() ); @@ -319,13 +319,14 @@ memory_partition_unit::memory_partition_unit( unsigned partition_id, m_stats=stats; m_dram = new dram_t(m_id,m_config,m_stats); - if( m_config->gpgpu_cache_dl2_opt ) { + if( m_config->m_L2_config.get_num_lines() ) { char L2c_name[32]; - snprintf(L2c_name, 32, "L2_%03d", m_id); - m_L2cache = new cache_t(L2c_name,m_config->gpgpu_cache_dl2_opt, write_through,-1,-1); - m_mshr = new L2c_mshr(m_L2cache->get_line_sz()); - m_missTracker = new L2c_miss_tracker(m_L2cache->get_line_sz()); - m_accessLocality = new L2c_access_locality(m_L2cache->get_line_sz()); + snprintf(L2c_name, 32, "L2_bank_%03d", m_id); + m_L2cache = new cache_t(L2c_name,m_config->m_L2_config,-1,-1); + unsigned l2_line_sz = m_config->m_L2_config.get_line_sz(); + m_mshr = new L2c_mshr( l2_line_sz ); + m_missTracker = new L2c_miss_tracker( l2_line_sz ); + m_accessLocality = new L2c_access_locality( l2_line_sz ); } else { m_L2cache=NULL; m_mshr=NULL; @@ -356,7 +357,7 @@ memory_partition_unit::memory_partition_unit( unsigned partition_id, L2todram_wbqueue = new fifo_pipeline("L2todram_wbqueue", L2c_L2_dm_minlength, L2c_L2_dm_minlength + m_config->gpgpu_dram_sched_queue_size + L2c_dm_L2_length, gpu_sim_cycle); L2dramout = NULL; wb_addr=-1; - if (m_config->gpgpu_cache_dl2_opt && 1) { + if (m_config->m_L2_config.get_num_lines() && 1) { cbtol2_Dist = StatCreate("cbtoL2",1, m_icnt2cache_queue->get_max_len()); cbtoL2wr_Dist = StatCreate("cbtoL2write",1, m_icnt2cache_write_queue->get_max_len()); L2tocb_Dist = StatCreate("L2tocb",1, L2tocbqueue->get_max_len()); @@ -478,7 +479,7 @@ void memory_partition_unit::process_dram_output() // it is the 1st or nth time trial to writeback if (wb_addr != (unsigned long long int)-1) { // performing L2 writeback (no false sharing for memory-side cache) - int wb_succeed = L2c_write_back(wb_addr, m_L2cache->get_line_sz()); + int wb_succeed = L2c_write_back(wb_addr, m_config->m_L2_config.get_line_sz()); if (!wb_succeed) { assert (L2dramout || wb_addr == (unsigned long long int)-1); return; diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index a316fbb..2c5de09 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -293,7 +293,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, class simt_core_cluster *cluster, unsigned shader_id, unsigned tpc_id, - struct shader_core_config *config, + const struct shader_core_config *config, const struct memory_config *mem_config, struct shader_core_stats *stats ) : m_barriers( config->max_warps_per_shader, config->max_cta_per_core ) @@ -304,8 +304,6 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_memory_config = mem_config; m_stats = stats; unsigned warp_size=config->warp_size; - config->max_sfu_latency = 32; - config->max_sp_latency = 32; m_sid = shader_id; m_tpc = tpc_id; @@ -332,7 +330,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, #define STRSIZE 1024 char L1I_name[STRSIZE]; snprintf(L1I_name, STRSIZE, "L1I_%03d", m_sid); - m_L1I = new cache_t(L1I_name,m_config->gpgpu_cache_il1_opt,no_writes,m_sid,get_shader_instruction_cache_id()); + m_L1I = new cache_t(L1I_name,m_config->m_L1I_config,m_sid,get_shader_instruction_cache_id()); m_warp.resize(m_config->max_warps_per_shader, shd_warp_t(this, warp_size)); m_pdom_warp = new pdom_warp_ctx_t*[config->max_warps_per_shader]; @@ -611,9 +609,9 @@ void shader_core_ctx::fetch() address_type ppc = pc + PROGRAM_MEM_START; address_type wb=0; unsigned nbytes=16; - unsigned offset_in_block = pc & (m_L1I->get_line_sz()-1); - if( (offset_in_block+nbytes) > m_L1I->get_line_sz() ) - nbytes = (m_L1I->get_line_sz()-offset_in_block); + unsigned offset_in_block = pc & (m_config->m_L1I_config.get_line_sz()-1); + if( (offset_in_block+nbytes) > m_config->m_L1I_config.get_line_sz() ) + nbytes = (m_config->m_L1I_config.get_line_sz()-offset_in_block); enum cache_request_status status = m_L1I->access( (unsigned long long)pc, 0, gpu_sim_cycle, &wb ); if( status != HIT ) { unsigned req_size = READ_PACKET_SIZE; @@ -813,182 +811,6 @@ mshr_entry* mshr_shader_unit::add_mshr(mem_access_t &access, warp_inst_t* pinst) return mshr; } -address_type line_size_based_tag_func(address_type address, unsigned line_size) -{ - //gives the tag for an address based on a given line size - return ((address) & (~((address_type)line_size - 1))); -} - -address_type null_tag_func(address_type address, unsigned line_size) -{ - return address; //no modification: each address is its own tag. -} - -unsigned shader_core_config::shmem_bank_func(address_type addr, unsigned) const -{ - return ((addr/WORD_SIZE) % gpgpu_n_shmem_bank); -} - -unsigned shader_core_config::dcache_bank_func(address_type add, unsigned line_size) const -{ - if (gpgpu_no_dl1) return 1; //no banks - else return (add / line_size) & (gpgpu_n_cache_bank - 1); -} - -void warp_inst_t::get_memory_access_list() -{ - // Calculates memory accesses generated by this warp - // Returns acesses which are "coalesced" - // Does not coalesce nor overlap bank accesses across warp "parts". - - // This is called once per warp_inst_t when the warp_inst_t enters the memory stage. - // It produces the set of distinct memory accesses that need to be peformed. - // These accessess are then performed over multiple cycles (stalling the pipeline) - // if the accessses cannot be performed all at once. - - // In hardware, these accesses would be created at the specific unit handling the type - // of memory access. We centralize the logic simply to reduce code duplication. - - // Below, accesses are assigned an "order" based on when that access may be issued. - // Accesses with the same order number may occur at the same time: they are to different banks. - // Later, when the queue is processed it will evaluate accesses of as many orders as - // ports on that cache/shmem. - // - // Accesses are placed in accessq sorted so that accesses of the same order are adjacent. - - bank_func_t bank_func = NULL; - tag_func_t tag_func = NULL; - unsigned warp_parts = 0; - unsigned line_size = 0; - bool limit_broadcast = 0; - bool global_mem_access = false; - - switch( space.get_type() ) { - case shared_space: - bank_func = &shader_core_config::shmem_bank_func; - tag_func = null_tag_func; - warp_parts = m_config->gpgpu_shmem_pipe_speedup; - line_size = 1; //shared memory doesn't care about line_size, needs to be at least 1; - limit_broadcast = true; // limit broadcasts to single cycle. - break; - case tex_space: - bank_func = &shader_core_config::null_bank_func; - tag_func = line_size_based_tag_func; - warp_parts = 1; - line_size = m_config->gpgpu_cache_texl1_linesize; - limit_broadcast = false; - break; - case const_space: case param_space_kernel: - bank_func = &shader_core_config::null_bank_func; - tag_func = line_size_based_tag_func; - warp_parts = 1; - line_size = m_config->gpgpu_cache_constl1_linesize; - limit_broadcast = false; - break; - case global_space: case local_space: case param_space_local: - global_mem_access=true; - warp_parts = 1; - line_size = m_config->gpgpu_cache_dl1_linesize; - if( m_config->gpgpu_coalesce_arch == 13 ){ - warp_parts = 2; - if( m_config->gpgpu_no_dl1 ) { - // line size is dependant on instruction; - switch (data_size) { - case 1: line_size = 32; break; - case 2: line_size = 64; break; - case 4: case 8: case 16: line_size = 128; break; - default: assert(0); - } - } - } - bank_func = &shader_core_config::dcache_bank_func; - tag_func = line_size_based_tag_func; - limit_broadcast = false; - break; - default: - abort(); - } - - // bank_accs tracks bank accesses for sorting into generations; - // each entry is (bank #, number of accesses) - // the idea is that you can only access a bank a number of times each cycle equal to - // its number of ports in one cycle. - std::map bank_accs; - - // keep track of broadcasts with unique orders if limit_broadcast - // the normally calculated orders will never be greater than warp_size - unsigned broadcast_order = warp_size(); - unsigned qbegin = get_accessq_size(); - unsigned qpartbegin = qbegin; - unsigned mem_pipe_size = warp_size() / warp_parts; - for (unsigned part = 0; part < warp_size(); part += mem_pipe_size) { - for (unsigned i = part; i < part + mem_pipe_size; i++) { - if ( !active(i) ) - continue; - new_addr_type addr = get_addr(i); - address_type lane_segment_address = tag_func(addr, line_size); - unsigned quarter = 0; - if( line_size>=4 ) - quarter = (addr / (line_size/4)) & 3; - bool match = false; - if( !isatomic() ) { //atomics must have own request - for( unsigned j = qpartbegin; j *bank_func)(get_addr(i), line_size); - // ensure no concurrent bank access accross warp parts. - // ie. order will be less than part for all previous loads in previous parts, so: - if (bank_accs[bank] < part) - bank_accs[bank]=part; - accessq_back().order = bank_accs[bank]; - bank_accs[bank]++; - } - } - qpartbegin = get_accessq_size(); //don't coalesce accross warp parts - } - //sort requests by order they will be processed in - std::stable_sort( m_accessq.begin()+qbegin,m_accessq.end()); - - if( global_mem_access ) { - // Now that we have the accesses, if we don't have a cache we can adjust request sizes to - // include only the data referenced by the threads - for (unsigned i = 0; i < get_accessq_size(); i++) { - if (m_config->gpgpu_coalesce_arch == 13 && m_config->gpgpu_no_dl1) { - // do coalescing here. - char* quarter_counts = accessq(i).quarter_count; - bool low = quarter_counts[0] or quarter_counts[1]; - bool high = quarter_counts[2] or quarter_counts[3]; - if (accessq(i).req_size == 128) { - if (low xor high) { //can reduce size - accessq(i).req_size = 64; - if (high) accessq(i).addr += 64; - low = quarter_counts[0] or quarter_counts[2]; //set low and high for next pass - high = quarter_counts[1] or quarter_counts[3]; - } - } - if (accessq(i).req_size == 64) { - if (low xor high) { //can reduce size - accessq(i).req_size = 32; - if (high) accessq(i).addr += 32; - } - } - } - } - } -} - void ldst_unit::const_cache_access(warp_inst_t &inst) { // do cache checks here for each request (non-physical), could be @@ -1400,11 +1222,41 @@ void ldst_unit::generate_mem_accesses(warp_inst_t &inst) inst.set_mem_accesses_created(); } + +simd_function_unit::simd_function_unit( const shader_core_config *config ) +{ + m_config=config; + m_dispatch_reg = new warp_inst_t(config); +} + +sfu::sfu( warp_inst_t **result_port, const shader_core_config *config ) + : pipelined_simd_unit(result_port,config,config->max_sfu_latency) +{ + m_name = "SFU"; +} + +sp_unit::sp_unit( warp_inst_t **result_port, const shader_core_config *config ) + : pipelined_simd_unit(result_port,config,config->max_sp_latency) +{ + m_name = "SP "; +} + + +pipelined_simd_unit::pipelined_simd_unit( warp_inst_t **result_port, const shader_core_config *config, unsigned max_latency ) + : simd_function_unit(config) +{ + m_result_port = result_port; + m_pipeline_depth = max_latency; + m_pipeline_reg = new warp_inst_t*[m_pipeline_depth]; + for( unsigned i=0; i < m_pipeline_depth; i++ ) + m_pipeline_reg[i] = new warp_inst_t( config ); +} + ldst_unit::ldst_unit( simt_core_cluster *cluster, shader_core_ctx *core, opndcoll_rfu_t *operand_collector, Scoreboard *scoreboard, - shader_core_config *config, + const shader_core_config *config, const memory_config *mem_config, shader_core_stats *stats, unsigned sid, @@ -1425,14 +1277,10 @@ ldst_unit::ldst_unit( simt_core_cluster *cluster, snprintf(L1D_name, STRSIZE, "L1D_%03d", m_sid); snprintf(L1T_name, STRSIZE, "L1T_%03d", m_sid); snprintf(L1C_name, STRSIZE, "L1C_%03d", m_sid); - enum cache_write_policy L1D_policy = m_config->gpgpu_cache_wt_through?write_through:write_back; - m_L1D = new cache_t(L1D_name,m_config->gpgpu_cache_dl1_opt,L1D_policy,m_sid,get_shader_normal_cache_id()); - m_L1T = new cache_t(L1T_name,m_config->gpgpu_cache_texl1_opt,no_writes, m_sid,get_shader_texture_cache_id()); - m_L1C = new cache_t(L1C_name,m_config->gpgpu_cache_constl1_opt,no_writes, m_sid,get_shader_constant_cache_id()); - config->gpgpu_cache_dl1_linesize = m_L1D->get_line_sz(); - config->gpgpu_cache_texl1_linesize = m_L1T->get_line_sz(); - config->gpgpu_cache_constl1_linesize = m_L1C->get_line_sz(); - m_cluster->get_gpu()->ptx_set_tex_cache_linesize(m_L1T->get_line_sz()); + m_L1D = new cache_t(L1D_name,m_config->m_L1D_config,m_sid,get_shader_normal_cache_id()); + m_L1T = new cache_t(L1T_name,m_config->m_L1T_config,m_sid,get_shader_texture_cache_id()); + m_L1C = new cache_t(L1C_name,m_config->m_L1C_config,m_sid,get_shader_constant_cache_id()); + m_cluster->get_gpu()->ptx_set_tex_cache_linesize(m_config->m_L1T_config.get_line_sz()); m_mshr_unit = new mshr_shader_unit(m_config); m_mem_rc = NO_RC_FAIL; } @@ -2401,7 +2249,7 @@ void opndcoll_rfu_t::collector_unit_t::init( unsigned n, warp_inst_t **port, unsigned num_banks, unsigned log2_warp_size, - const shader_core_config *config, + const core_config *config, opndcoll_rfu_t *rfu ) { m_rfu=rfu; @@ -2456,7 +2304,7 @@ class ptx_thread_info *shader_core_ctx::get_thread_state( unsigned hw_thread_id simt_core_cluster::simt_core_cluster( class gpgpu_sim *gpu, unsigned cluster_id, - struct shader_core_config *config, + const struct shader_core_config *config, const struct memory_config *mem_config, struct shader_core_stats *stats ) { diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 85d5ac1..786913a 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -662,7 +662,7 @@ private: warp_inst_t **port, unsigned num_banks, unsigned log2_warp_size, - const shader_core_config *config, + const core_config *config, opndcoll_rfu_t *rfu ); void allocate( warp_inst_t *&pipeline_reg ); @@ -867,11 +867,7 @@ struct ifetch_buffer_t { class simd_function_unit { public: - simd_function_unit( const shader_core_config *config ) - { - m_config=config; - m_dispatch_reg = new warp_inst_t(config); - } + simd_function_unit( const shader_core_config *config ); ~simd_function_unit() { delete m_dispatch_reg; } // modifiers @@ -894,15 +890,7 @@ protected: class pipelined_simd_unit : public simd_function_unit { public: - pipelined_simd_unit( warp_inst_t **result_port, const shader_core_config *config, unsigned max_latency ) - : simd_function_unit(config) - { - m_result_port = result_port; - m_pipeline_depth = max_latency; - m_pipeline_reg = new warp_inst_t*[m_pipeline_depth]; - for( unsigned i=0; i < m_pipeline_depth; i++ ) - m_pipeline_reg[i] = new warp_inst_t( config ); - } + pipelined_simd_unit( warp_inst_t **result_port, const shader_core_config *config, unsigned max_latency ); //modifiers virtual void cycle() @@ -948,8 +936,7 @@ protected: class sfu : public pipelined_simd_unit { public: - sfu( warp_inst_t **result_port, const shader_core_config *config ) - : pipelined_simd_unit(result_port,config,config->max_sfu_latency) { m_name = "SFU"; } + sfu( warp_inst_t **result_port, const shader_core_config *config ); virtual bool can_issue( const warp_inst_t &inst ) const { switch(inst.op) { @@ -964,8 +951,7 @@ public: class sp_unit : public pipelined_simd_unit { public: - sp_unit( warp_inst_t **result_port, const shader_core_config *config ) - : pipelined_simd_unit(result_port,config,config->max_sp_latency) { m_name = "SP "; } + sp_unit( warp_inst_t **result_port, const shader_core_config *config ); virtual bool can_issue( const warp_inst_t &inst ) const { switch(inst.op) { @@ -987,7 +973,7 @@ public: shader_core_ctx *core, opndcoll_rfu_t *operand_collector, Scoreboard *scoreboard, - shader_core_config *config, + const shader_core_config *config, const memory_config *mem_config, shader_core_stats *stats, unsigned sid, unsigned tpc ); @@ -1066,6 +1052,71 @@ enum pipeline_stage_name_t { N_PIPELINE_STAGES }; +struct shader_core_config : public core_config +{ + void init() + { + max_warps_per_shader = n_thread_per_shader/warp_size; + assert( !(n_thread_per_shader % warp_size) ); + + max_sfu_latency = 32; + max_sp_latency = 32; + + m_L1I_config.init(); + m_L1T_config.init(); + m_L1C_config.init(); + m_L1D_config.init(); + gpgpu_cache_dl1_linesize = m_L1D_config.get_line_sz(); + gpgpu_cache_texl1_linesize = m_L1T_config.get_line_sz(); + gpgpu_cache_constl1_linesize = m_L1C_config.get_line_sz(); + + m_valid = true; + } + + bool gpgpu_perfect_mem; + enum divergence_support_t model; + unsigned n_thread_per_shader; + unsigned max_warps_per_shader; + unsigned max_cta_per_core; //Limit on number of concurrent CTAs in shader core + unsigned pdom_sched_type; + + cache_config m_L1I_config; + cache_config m_L1T_config; + cache_config m_L1C_config; + cache_config m_L1D_config; + + unsigned n_mshr_per_shader; + bool gpgpu_dwf_reg_bankconflict; + int gpgpu_operand_collector_num_units_sp; + int gpgpu_operand_collector_num_units_sfu; + int gpgpu_operand_collector_num_units_mem; + bool gpgpu_stall_on_use; + //Shader core resources + unsigned gpgpu_shmem_size; + unsigned gpgpu_shader_registers; + int gpgpu_warpdistro_shader; + int gpgpu_interwarp_mshr_merge; + int gpgpu_shmem_port_per_bank; + int gpgpu_cache_port_per_bank; + int gpgpu_const_port_per_bank; + unsigned gpgpu_num_reg_banks; + unsigned gpu_max_cta_per_shader; // TODO: modify this for fermi... computed based upon kernel + // resource usage; used in shader_core_ctx::translate_local_memaddr + bool gpgpu_reg_bank_use_warp_id; + bool gpgpu_local_mem_map; + int gpu_padded_cta_size; + + unsigned max_sp_latency; + unsigned max_sfu_latency; + + unsigned n_simt_cores_per_cluster; + unsigned n_simt_clusters; + unsigned n_simt_ejection_buffer_size; + unsigned ldst_unit_response_queue_size; + + unsigned mem2device(unsigned memid) const { return memid + n_simt_clusters; } +}; + class shader_core_ctx : public core_t { public: @@ -1073,7 +1124,7 @@ public: class simt_core_cluster *cluster, unsigned shader_id, unsigned tpc_id, - struct shader_core_config *config, + const struct shader_core_config *config, const struct memory_config *mem_config, struct shader_core_stats *stats ); @@ -1190,7 +1241,7 @@ class simt_core_cluster { public: simt_core_cluster( class gpgpu_sim *gpu, unsigned cluster_id, - struct shader_core_config *config, + const struct shader_core_config *config, const struct memory_config *mem_config, struct shader_core_stats *stats ); diff --git a/src/gpgpu-sim/stats.h b/src/gpgpu-sim/stats.h index 20acfa1..8115eae 100644 --- a/src/gpgpu-sim/stats.h +++ b/src/gpgpu-sim/stats.h @@ -90,7 +90,7 @@ enum mem_stage_stall_type { N_MEM_STAGE_STALL_TYPE }; -struct shader_core_stats +struct shader_core_stats { unsigned int gpgpu_n_load_insn; unsigned int gpgpu_n_store_insn; -- cgit v1.3