diff options
| author | Tor Aamodt <[email protected]> | 2010-10-16 17:30:52 -0800 |
|---|---|---|
| committer | Tor Aamodt <[email protected]> | 2010-10-16 17:30:52 -0800 |
| commit | b577cbcdf229a2c02d1bf8584c6e82be7a14cb33 (patch) | |
| tree | 373ea8ec8ea8d7d9a7a1df0eaa17f15652df1306 /src/gpgpu-sim/shader.cc | |
| parent | 2072e7ff2037c19a0c346e60469949c9437569bf (diff) | |
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]
Diffstat (limited to 'src/gpgpu-sim/shader.cc')
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 236 |
1 files changed, 42 insertions, 194 deletions
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<unsigned,unsigned> 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 <get_accessq_size(); j++ ) { - if (lane_segment_address == accessq(j).addr) { - accessq(j).quarter_count[quarter]++; - accessq(j).warp_indices.push_back(i); - if (limit_broadcast) // two threads access this address, so its a broadcast. - accessq(j).order = ++broadcast_order; //do broadcast in its own cycle. - match = true; - break; - } - } - } - if (!match) { // does not match a previous request by another thread, so need a new request - assert( space != undefined_space ); - m_accessq.push_back( mem_access_t( lane_segment_address, line_size, quarter, i) ); - // Determine Bank Conflicts: - unsigned bank = (m_config->*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 ) { |
