From e1cffaf08733754ab55052b6a2729dae57665d29 Mon Sep 17 00:00:00 2001 From: Inderpreet Singh Date: Wed, 25 May 2011 16:01:16 -0800 Subject: Fix bug #100: local memory address translation returns multiple addresses Fix bug #101: Coalescing allows multiple accesses per thread for local memory access This will break atomics which assume at most one thread per mem_fetch. It did not break scoreboard as that logic tracks mem_fetches at warp level, not thread level. [git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 9303] --- src/abstract_hardware_model.cc | 33 ++++++++++++++++++++++----------- src/abstract_hardware_model.h | 18 ++++++++++++++---- src/gpgpu-sim/shader.cc | 31 +++++++++++++++++++++---------- src/gpgpu-sim/shader.h | 4 +++- 4 files changed, 60 insertions(+), 26 deletions(-) diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index e883455..1cce2f2 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -123,7 +123,7 @@ void warp_inst_t::generate_mem_accesses() for( unsigned thread=subwarp*subwarp_size; thread < (subwarp+1)*subwarp_size; thread++ ) { if( !active(thread) ) continue; - new_addr_type addr = m_per_scalar_thread[thread].memreqaddr; + new_addr_type addr = m_per_scalar_thread[thread].memreqaddr[0]; //FIXME: deferred allocation of shared memory should not accumulate across kernel launches //assert( addr < m_config->gpgpu_shmem_size ); unsigned bank = m_config->shmem_bank_func(addr); @@ -211,15 +211,26 @@ void warp_inst_t::generate_mem_accesses() for( unsigned thread=subwarp*subwarp_size; threadwarp_size; thread++ ) { if( !active(thread) ) continue; - new_addr_type addr = m_per_scalar_thread[thread].memreqaddr; + new_addr_type addr = m_per_scalar_thread[thread].memreqaddr[0]; unsigned block_address = line_size_based_tag_func(addr,cache_block_size); accesses[block_address].set(thread); unsigned idx = addr-block_address; diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 2332670..bb4545e 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -655,7 +655,16 @@ public: m_per_scalar_thread.resize(m_config->warp_size); m_per_scalar_thread_valid=true; } - m_per_scalar_thread[n].memreqaddr = addr; + m_per_scalar_thread[n].memreqaddr[0] = addr; + } + void set_addr( unsigned n, new_addr_type* addr, unsigned num_addrs ) + { + if( !m_per_scalar_thread_valid ) { + m_per_scalar_thread.resize(m_config->warp_size); + m_per_scalar_thread_valid=true; + } + for(unsigned i=0; i m_per_scalar_thread; diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 855e1c2..166ba88 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -646,9 +646,13 @@ void shader_core_ctx::func_exec_inst( warp_inst_t &inst ) m_thread[tid].m_functional_model_thread_state->ptx_exec_inst(inst,t); if( inst.has_callback(t) ) m_warp[inst.warp_id()].inc_n_atomic(); - if (inst.space.is_local() && (inst.is_load() || inst.is_store())) - inst.set_addr(t, translate_local_memaddr(inst.get_addr(t), tid, - m_config->n_simt_clusters*m_config->n_simt_cores_per_cluster) ); + if (inst.space.is_local() && (inst.is_load() || inst.is_store())) { + new_addr_type localaddrs[8]; + unsigned num_addrs; + num_addrs = translate_local_memaddr(inst.get_addr(t), tid, m_config->n_simt_clusters*m_config->n_simt_cores_per_cluster, + inst.data_size, (new_addr_type*) localaddrs ); + inst.set_addr(t, (new_addr_type*) localaddrs, num_addrs); + } if ( ptx_thread_done(tid) ) { m_warp[inst.warp_id()].set_completed(t); m_warp[inst.warp_id()].ibuffer_flush(); @@ -793,7 +797,8 @@ address_type coalesced_segment(address_type addr, unsigned segment_size_lg2bytes return (addr >> segment_size_lg2bytes); } -address_type shader_core_ctx::translate_local_memaddr( address_type localaddr, unsigned tid, unsigned num_shader ) +// Returns numbers of addresses in translated_addrs, each addr points to a 4B (32-bit) word +unsigned shader_core_ctx::translate_local_memaddr( address_type localaddr, unsigned tid, unsigned num_shader, unsigned datasize, new_addr_type* translated_addrs ) { // During functional execution, each thread sees its own memory space for local memory, but these // need to be mapped to a shared address space for timing simulation. We do that mapping here. @@ -824,10 +829,16 @@ address_type shader_core_ctx::translate_local_memaddr( address_type localaddr, u } assert( thread_base < 4/*word size*/*max_concurrent_threads ); - address_type local_word = localaddr/4; - address_type word_offset = localaddr%4; - address_type linear_address = local_word*max_concurrent_threads + thread_base + word_offset; - return linear_address; + assert(datasize%4 == 0); + assert(datasize >= 4); + assert(datasize <= 32); // max 32B + assert(localaddr%4 == 0); // Required if accessing 4B per request, otherwise access will overflow into next thread's space + for(unsigned i=0; ialloc(inst,access); m_icnt->push(mf); inst.accessq_pop_back(); - inst.clear_active( access.get_warp_mask() ); + //inst.clear_active( access.get_warp_mask() ); if( inst.is_load() ) { for( unsigned r=0; r < 4; r++) if(inst.out[r] > 0) diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 8d6c290..7cb3af7 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1242,7 +1242,9 @@ private: friend class scheduler_unit; //this is needed to use private issue warp. void issue_warp( warp_inst_t *&warp, const warp_inst_t *pI, const active_mask_t &active_mask, unsigned warp_id ); void func_exec_inst( warp_inst_t &inst ); - address_type translate_local_memaddr(address_type localaddr, unsigned tid, unsigned num_shader ); + + // Returns numbers of addresses in translated_addrs + unsigned translate_local_memaddr( address_type localaddr, unsigned tid, unsigned num_shader, unsigned datasize, new_addr_type* translated_addrs ); void read_operands(); -- cgit v1.3