diff options
| author | Inderpreet Singh <[email protected]> | 2011-05-25 16:01:16 -0800 |
|---|---|---|
| committer | Inderpreet Singh <[email protected]> | 2011-05-25 16:01:16 -0800 |
| commit | e1cffaf08733754ab55052b6a2729dae57665d29 (patch) | |
| tree | 6bd1fda8aedad981d8295fdf765c85df1e1c8f3d /src/abstract_hardware_model.cc | |
| parent | 07376c3d981fbfea6bfad99657c2055b9bdb0e4f (diff) | |
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]
Diffstat (limited to 'src/abstract_hardware_model.cc')
| -rw-r--r-- | src/abstract_hardware_model.cc | 33 |
1 files changed, 22 insertions, 11 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; thread<subwarp_size*(subwarp+1); thread++ ) { if( !active(thread) ) continue; - new_addr_type addr = m_per_scalar_thread[thread].memreqaddr; - unsigned block_address = line_size_based_tag_func(addr,segment_size); - unsigned chunk = (addr&127)/32; // which 32-byte chunk within in a 128-byte chunk does this thread access? - transaction_info &info = subwarp_transactions[block_address]; - info.chunks.set(chunk); - info.active.set(thread); - unsigned idx = (addr&127); - for( unsigned i=0; i < data_size; i++ ) - info.bytes.set(idx+i); + + // local memory can only be accessed in 4B chunks by one thread + unsigned data_size_coales = (space.get_type() == local_space || space.get_type() == param_space_local ) ? 4 : data_size; + unsigned num_accesses = (space.get_type() == local_space || space.get_type() == param_space_local ) ? data_size/4 : 1; + + for(unsigned access=0; access<num_accesses; access++) { + new_addr_type addr = m_per_scalar_thread[thread].memreqaddr[access]; + unsigned block_address = line_size_based_tag_func(addr,segment_size); + unsigned chunk = (addr&127)/32; // which 32-byte chunk within in a 128-byte chunk does this thread access? + transaction_info &info = subwarp_transactions[block_address]; + + // can only write to one segment + assert(block_address == line_size_based_tag_func(addr+data_size_coales-1,segment_size)); + + info.chunks.set(chunk); + info.active.set(thread); + unsigned idx = (addr&127); + for( unsigned i=0; i < data_size_coales; i++ ) + info.bytes.set(idx+i); + } } // step 2: reduce each transaction size, if possible @@ -293,7 +304,7 @@ void warp_inst_t::generate_mem_accesses() for( unsigned thread=0; thread < m_config->warp_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; |
