diff options
| author | Tor Aamodt <[email protected]> | 2010-10-21 07:16:49 -0800 |
|---|---|---|
| committer | Tor Aamodt <[email protected]> | 2010-10-21 07:16:49 -0800 |
| commit | dc93f319051a9a9936a02cd9c1f7843a382a2da0 (patch) | |
| tree | 6c042ccab67be43b8fe442ab435ffbfd0f34e56e /src | |
| parent | ee5ea34857e4ecc6c63d4971e549076c6a9888ba (diff) | |
1. rewriting memory access generation code (from scratch), why not...
passing CUDA 3.1 and ptxplus correlation, but correlation still bad (0.62)...
after debugging 1 to get it working with ptxplus, problem is very clear:
shared and constant cache accesses not occuring for operations that combine these with ALU operations.
TODO:
have a "read-operands" stage, which somehow combines operand collector
register reading with shared and const memory accesses...
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7895]
Diffstat (limited to 'src')
| -rw-r--r-- | src/abstract_hardware_model.cc | 368 | ||||
| -rw-r--r-- | src/abstract_hardware_model.h | 177 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.cc | 6 | ||||
| -rw-r--r-- | src/gpgpu-sim/mem_fetch.cc | 42 | ||||
| -rw-r--r-- | src/gpgpu-sim/mem_fetch.h | 59 | ||||
| -rw-r--r-- | src/gpgpu-sim/mem_latency_stat.cc | 2 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 213 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.h | 5 | ||||
| -rw-r--r-- | src/gpgpu-sim/visualizer.cc | 4 |
9 files changed, 438 insertions, 438 deletions
diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index 507e02f..ad5c983 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -2,7 +2,7 @@ #include "cuda-sim/memory.h" #include <algorithm> -unsigned mem_access_t::next_access_uid = 0; +unsigned mem_access_t::sm_next_access_uid = 0; unsigned warp_inst_t::sm_next_uid = 0; void move_warp( warp_inst_t *&dst, warp_inst_t *&src ) @@ -24,173 +24,241 @@ gpgpu_t::gpgpu_t() m_dev_malloc=GLOBAL_HEAP_START; } -unsigned core_config::shmem_bank_func(address_type addr, unsigned) const -{ - return ((addr/WORD_SIZE) % gpgpu_n_shmem_bank); -} - -address_type null_tag_func(address_type address, unsigned line_size) -{ - return address; //no modification: each address is its own tag. -} - -address_type line_size_based_tag_func(address_type address, unsigned line_size) +address_type line_size_based_tag_func(new_addr_type address, new_addr_type line_size) { //gives the tag for an address based on a given line size - return ((address) & (~((address_type)line_size - 1))); + return address & ~(line_size-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". +struct transaction_info { + std::bitset<4> chunks; // bitmask: 32-byte chunks accessed + mem_access_byte_mask_t bytes; + active_mask_t active; // threads in this transaction +}; - // 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. +void warp_inst_t::generate_mem_accesses() +{ + if( empty() || op == MEMORY_BARRIER_OP || m_mem_accesses_created ) + return; + if ( !( (op == LOAD_OP) || (op == STORE_OP) || (op == MEMORY_BARRIER_OP) ) ) + return; - // 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. + assert( is_load() || is_store() ); + assert( m_per_scalar_thread_valid ); // need address information per thread - typedef unsigned (core_config::*bank_func_t)(address_type add, unsigned line_size) const; - typedef address_type (*tag_func_t)(address_type add, unsigned line_size); - 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; + bool is_write = is_store(); - switch( space.get_type() ) { - case shared_space: - bank_func = &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. + mem_access_type access_type; + switch (space.get_type()) { + case const_space: + case param_space_kernel: + access_type = CONST_ACC_R; break; case tex_space: - bank_func = &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; + access_type = TEXTURE_ACC_R; break; - case const_space: case param_space_kernel: - bank_func = &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; + case global_space: + access_type = is_write? GLOBAL_ACC_W: GLOBAL_ACC_R; break; - case global_space: case local_space: case param_space_local: - global_mem_access=true; - warp_parts = 1; - line_size = 0; - if( m_config->gpgpu_coalesce_arch == 13 ){ - warp_parts = 2; - // 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); - } - } else abort(); - bank_func = &core_config::null_bank_func; - tag_func = line_size_based_tag_func; - limit_broadcast = false; + case local_space: + case param_space_local: + access_type = is_write? LOCAL_ACC_W: LOCAL_ACC_R; break; - default: - abort(); + case shared_space: break; + default: assert(0); break; } - // 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; + // Calculate memory accesses generated by this warp + new_addr_type cache_block_size = 32; // in bytes + + switch( space.get_type() ) { + case shared_space: { + unsigned subwarp_size = m_config->warp_size / m_config->shmem_warp_parts; + unsigned total_accesses=0; + for( unsigned subwarp=0; subwarp < m_config->shmem_warp_parts; subwarp++ ) { + + // data structures used per part warp + std::map<unsigned,std::map<new_addr_type,unsigned> > bank_accs; // bank -> word address -> access count - // 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; - } + // step 1: compute accesses to words in banks + 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; + unsigned bank = m_config->shmem_bank_func(addr); + new_addr_type word = line_size_based_tag_func(addr,m_config->WORD_SIZE); + bank_accs[bank][word]++; } - } - 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) { - // 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]; + // step 2: look for and select a broadcast bank/word if one occurs + bool broadcast_detected = false; + new_addr_type broadcast_word=(new_addr_type)-1; + unsigned broadcast_bank=(unsigned)-1; + std::map<unsigned,std::map<new_addr_type,unsigned> >::iterator b; + for( b=bank_accs.begin(); b != bank_accs.end(); b++ ) { + unsigned bank = b->first; + std::map<new_addr_type,unsigned> &access_set = b->second; + std::map<new_addr_type,unsigned>::iterator w; + for( w=access_set.begin(); w != access_set.end(); ++w ) { + if( w->second > 1 ) { + // found a broadcast + broadcast_detected=true; + broadcast_bank=bank; + broadcast_word=w->first; + break; + } } - } - if (accessq(i).req_size == 64) { - if (low xor high) { //can reduce size - accessq(i).req_size = 32; - if (high) accessq(i).addr += 32; + if( broadcast_detected ) + break; + } + + // step 3: figure out max bank accesses performed, taking account of broadcast case + unsigned max_bank_accesses=0; + for( b=bank_accs.begin(); b != bank_accs.end(); b++ ) { + unsigned bank_accesses=0; + std::map<new_addr_type,unsigned> &access_set = b->second; + std::map<new_addr_type,unsigned>::iterator w; + for( w=access_set.begin(); w != access_set.end(); ++w ) + bank_accesses += w->second; + if( broadcast_detected && broadcast_bank == b->first ) { + for( w=access_set.begin(); w != access_set.end(); ++w ) { + if( w->first == broadcast_word ) { + unsigned n = w->second; + assert(n > 1); // or this wasn't a broadcast + assert(bank_accesses >= (n-1)); + bank_accesses -= (n-1); + break; + } + } } - } - } - } - } -} + if( bank_accesses > max_bank_accesses ) + max_bank_accesses = bank_accesses; + } + + // step 4: accumulate + total_accesses+= max_bank_accesses; + } + assert( total_accesses > 0 && total_accesses <= m_config->warp_size ); + cycles = total_accesses; // shared memory conflicts modeled as larger initiation interval + break; + } + case tex_space: + cache_block_size = m_config->gpgpu_cache_texl1_linesize; + + case const_space: case param_space_kernel: + cache_block_size = m_config->gpgpu_cache_constl1_linesize; { + mem_access_byte_mask_t byte_mask; + std::map<new_addr_type,active_mask_t> accesses; // block address -> set of thread offsets in warp + std::map<new_addr_type,active_mask_t>::iterator a; + for( unsigned thread=0; thread < m_config->warp_size; thread++ ) { + if( !active(thread) ) + continue; + new_addr_type addr = m_per_scalar_thread[thread].memreqaddr; + unsigned block_address = line_size_based_tag_func(addr,m_config->gpgpu_cache_texl1_linesize); + accesses[block_address].set(thread); + unsigned idx = addr-block_address; + for( unsigned i=0; i < data_size; i++ ) + byte_mask.set(idx+i); + } + for( a=accesses.begin(); a != accesses.end(); ++a ) + m_accessq.push_back( mem_access_t(access_type,a->first,cache_block_size,is_write,a->second,byte_mask) ); + } + break; + + case global_space: case local_space: case param_space_local: + + if( m_config->gpgpu_coalesce_arch == 13 ) { + // see the CUDA manual where it discusses coalescing rules before reading this + unsigned segment_size = 0; + unsigned warp_parts = 2; + switch( data_size ) { + case 1: segment_size = 32; break; + case 2: segment_size = 64; break; + case 4: case 8: case 16: segment_size = 128; break; + } + unsigned subwarp_size = m_config->warp_size / warp_parts; + + for( unsigned subwarp=0; subwarp < warp_parts; subwarp++ ) { + std::map<new_addr_type,transaction_info> subwarp_transactions; + + // step 1: find all transactions generated by this subwarp + 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); + } + + // step 2: reduce each transaction size, if possible + std::map< new_addr_type, transaction_info >::iterator t; + for( t=subwarp_transactions.begin(); t !=subwarp_transactions.end(); t++ ) { + new_addr_type addr = t->first; + assert( (addr & (segment_size-1)) == 0 ); + const transaction_info &info = t->second; + const std::bitset<4> &q = info.chunks; + assert( q.count() >= 1 ); + std::bitset<2> h; // halves (used to check if 64 byte segment can be compressed into a single 32 byte segment) + + unsigned size=segment_size; + if( segment_size == 128 ) { + bool lower_half_used = q[0] || q[1]; + bool upper_half_used = q[2] || q[3]; + if( lower_half_used && !upper_half_used ) { + // only lower 64 bytes used + size = 64; + if(q[0]) h.set(0); + if(q[1]) h.set(1); + } else if ( (!lower_half_used) && upper_half_used ) { + // only upper 64 bytes used + addr = addr+64; + size = 64; + if(q[2]) h.set(0); + if(q[3]) h.set(1); + } else { + assert(lower_half_used && upper_half_used); + } + } else if( segment_size == 64 ) { + // need to set halves + if( (addr % 128) == 0 ) { + if(q[0]) h.set(0); + if(q[1]) h.set(1); + } else { + assert( (addr % 128) == 64 ); + if(q[2]) h.set(0); + if(q[3]) h.set(1); + } + } + if( size == 64 ) { + bool lower_half_used = h[0]; + bool upper_half_used = h[1]; + if( lower_half_used && !upper_half_used ) { + size = 32; + } else if ( (!lower_half_used) && upper_half_used ) { + addr = addr+32; + size = 32; + } else { + assert(lower_half_used && upper_half_used); + } + } + m_accessq.push_back( mem_access_t(access_type,addr,size,is_write,info.active,info.bytes) ); + } + } + + } else abort(); + + break; + + default: + abort(); + } + + m_mem_accesses_created=true; +} diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index fc2f0d4..804cf23 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -160,16 +160,21 @@ struct core_config { bool m_valid; unsigned warp_size; - // memory request architecture parameters + // off-chip memory request architecture parameters int gpgpu_coalesce_arch; - int gpgpu_shmem_pipe_speedup; - unsigned gpgpu_cache_texl1_linesize; - unsigned gpgpu_cache_constl1_linesize; + // shared memory bank conflict checking parameters static const address_type WORD_SIZE=4; - unsigned null_bank_func(address_type, unsigned) const { return 1; } - int gpgpu_n_shmem_bank; - unsigned shmem_bank_func(address_type addr, unsigned) const; + int num_shmem_bank; + unsigned shmem_bank_func(address_type addr) const + { + return ((addr/WORD_SIZE) % num_shmem_bank); + } + unsigned shmem_warp_parts; + + // texture and constant cache line sizes (used to determine number of memory accesses) + unsigned gpgpu_cache_texl1_linesize; + unsigned gpgpu_cache_constl1_linesize; }; class core_t { @@ -352,57 +357,94 @@ private: unsigned m_bank; // n in ".const[n]"; note .const == .const[0] (see PTX 2.1 manual, sec. 5.1.3) }; +const unsigned MAX_MEMORY_ACCESS_SIZE = 128; +typedef std::bitset<MAX_MEMORY_ACCESS_SIZE> mem_access_byte_mask_t; +#define NO_PARTIAL_WRITE (mem_access_byte_mask_t()) + +const unsigned MAX_WARP_SIZE = 32; +typedef std::bitset<MAX_WARP_SIZE> active_mask_t; + +enum mem_access_type { + GLOBAL_ACC_R, + LOCAL_ACC_R, + CONST_ACC_R, + TEXTURE_ACC_R, + GLOBAL_ACC_W, + LOCAL_ACC_W, + L2_WRBK_ACC, + INST_ACC_R, + NUM_MEM_ACCESS_TYPE +}; + class mem_access_t { public: - mem_access_t() - { - init(); + mem_access_t() { init(); } + mem_access_t( mem_access_type type, + address_type address, + unsigned size, + bool wr ) + { + init(); + m_type = type; + m_addr = address; + m_req_size = size; + m_write = wr; } - mem_access_t(address_type address, unsigned size, unsigned quarter, unsigned idx ) + mem_access_t( mem_access_type type, + address_type address, + unsigned size, + bool wr, + const active_mask_t &active_mask, + const mem_access_byte_mask_t &byte_mask ) + : m_warp_mask(active_mask), m_byte_mask(byte_mask) { init(); - addr = address; - req_size = size; - quarter_count[quarter]++; - warp_indices.push_back(idx); + m_type = type; + m_addr = address; + m_req_size = size; + m_write = wr; } - bool operator<(const mem_access_t &other) const {return (order > other.order);}//this is reverse + new_addr_type get_addr() const { return m_addr; } + unsigned get_size() const { return m_req_size; } + const active_mask_t &get_warp_mask() const { return m_warp_mask; } + bool is_write() const { return m_write; } + enum mem_access_type get_type() const { return m_type; } + mem_access_byte_mask_t get_byte_mask() const { return m_byte_mask; } + + void print(FILE *fp) const + { + fprintf(fp,"addr=0x%llx, %s, size=%u, ", m_addr, m_write?"store":"load ", m_req_size ); + switch(m_type) { + case GLOBAL_ACC_R: fprintf(fp,"GLOBAL_R"); break; + case LOCAL_ACC_R: fprintf(fp,"LOCAL_R "); break; + case CONST_ACC_R: fprintf(fp,"CONST "); break; + case TEXTURE_ACC_R: fprintf(fp,"TEXTURE "); break; + case GLOBAL_ACC_W: fprintf(fp,"GLOBAL_W"); break; + case LOCAL_ACC_W: fprintf(fp,"LOCAL_W "); break; + case L2_WRBK_ACC: fprintf(fp,"L2_WRBK "); break; + case INST_ACC_R: fprintf(fp,"INST "); break; + default: fprintf(fp,"unknown "); break; + } + } private: void init() { - uid=++next_access_uid; - addr=0; - req_size=0; - order=0; - _quarter_count_all=0; - cache_hit = false; - cache_checked = false; - recheck_cache = false; - need_wb = false; - wb_addr = 0; + m_uid=++sm_next_access_uid; + m_addr=0; + m_req_size=0; } -public: - - unsigned uid; - address_type addr; //address of the segment to load. - unsigned req_size; //bytes - unsigned order; // order of accesses, based on banks. - union{ - unsigned _quarter_count_all; - char quarter_count[4]; //access counts to each quarter of segment, for compaction; - }; - std::vector<unsigned> warp_indices; // warp indicies for this request. - bool cache_hit; - bool cache_checked; - bool recheck_cache; - bool need_wb; - address_type wb_addr; // writeback address (if necessary). + unsigned m_uid; + new_addr_type m_addr; // request address + bool m_write; + unsigned m_req_size; // bytes + mem_access_type m_type; + active_mask_t m_warp_mask; + mem_access_byte_mask_t m_byte_mask; -private: - static unsigned next_access_uid; + static unsigned sm_next_access_uid; }; class mem_fetch; @@ -471,8 +513,6 @@ protected: virtual void pre_decode() {} }; -#define MAX_WARP_SIZE 32 - enum divergence_support_t { POST_DOMINATOR = 1, NUM_SIMD_MODEL @@ -518,7 +558,7 @@ public: { for (int i=(int)m_config->warp_size-1; i>=0; i--) { if( mask & (1<<i) ) - warp_active_mask.set(i); + m_warp_active_mask.set(i); } m_uid = ++sm_next_uid; m_warp_id = warp_id; @@ -535,6 +575,7 @@ public: } m_per_scalar_thread[n].memreqaddr = addr; } + void generate_mem_accesses(); void add_callback( unsigned lane_id, void (*function)(const class inst_t*, class ptx_thread_info*), const inst_t *inst, @@ -549,17 +590,12 @@ public: m_per_scalar_thread[lane_id].callback.instruction = inst; m_per_scalar_thread[lane_id].callback.thread = thread; } - void set_active( std::vector<unsigned> &active ) + void set_active( const active_mask_t &active ) { - warp_active_mask.reset(); - for( std::vector<unsigned>::iterator i=active.begin(); i!=active.end(); ++i ) { - unsigned t = *i; - assert( t < m_config->warp_size ); - warp_active_mask.set(t); - } + m_warp_active_mask = active; if( m_isatomic ) { for( unsigned i=0; i < m_config->warp_size; i++ ) { - if( !warp_active_mask.test(i) ) { + if( !m_warp_active_mask.test(i) ) { m_per_scalar_thread[i].callback.function = NULL; m_per_scalar_thread[i].callback.instruction = NULL; m_per_scalar_thread[i].callback.thread = NULL; @@ -567,29 +603,27 @@ public: } } } - void clear_active( std::vector<unsigned> &inactive ) + void clear_active( const active_mask_t &inactive ) { - std::vector<unsigned>::iterator i; - for(i=inactive.begin(); i!=inactive.end();i++) { - unsigned t=*i; - warp_active_mask.reset(t); - } + active_mask_t test = m_warp_active_mask; + test &= inactive; + assert( test == inactive ); // verify threads being disabled were active + m_warp_active_mask &= ~inactive; } void set_not_active( unsigned lane_id ) { - warp_active_mask.reset(lane_id); + m_warp_active_mask.reset(lane_id); } - void get_memory_access_list(); // accessors virtual void print_insn(FILE *fp) const { fprintf(fp," [inst @ pc=0x%04x] ", pc ); for (int i=(int)m_config->warp_size-1; i>=0; i--) - fprintf(fp, "%c", ((warp_active_mask[i])?'1':'0') ); + fprintf(fp, "%c", ((m_warp_active_mask[i])?'1':'0') ); } - bool active( unsigned thread ) const { return warp_active_mask.test(thread); } - unsigned active_count() const { return warp_active_mask.count(); } + bool active( unsigned thread ) const { return m_warp_active_mask.test(thread); } + unsigned active_count() const { return m_warp_active_mask.count(); } bool empty() const { return m_empty; } unsigned warp_id() const { @@ -598,7 +632,7 @@ public: } bool has_callback( unsigned n ) const { - return warp_active_mask[n] && m_per_scalar_thread_valid && + return m_warp_active_mask[n] && m_per_scalar_thread_valid && (m_per_scalar_thread[n].callback.function!=NULL); } new_addr_type get_addr( unsigned n ) const @@ -611,12 +645,8 @@ public: unsigned warp_size() const { return m_config->warp_size; } - bool mem_accesses_created() const { return m_mem_accesses_created; } - void set_mem_accesses_created() { m_mem_accesses_created=true; } bool accessq_empty() const { return m_accessq.empty(); } - unsigned get_accessq_size() const { return m_accessq.size(); } - mem_access_t &accessq( unsigned n ) { return m_accessq[n]; } - mem_access_t &accessq_back() { return m_accessq.back(); } + const mem_access_t &accessq_back() { return m_accessq.back(); } void accessq_pop_back() { m_accessq.pop_back(); } bool dispatch_delay() @@ -629,6 +659,7 @@ public: void print( FILE *fout ) const; protected: + unsigned m_uid; bool m_empty; bool m_cache_hit; @@ -637,7 +668,7 @@ protected: bool m_isatomic; unsigned m_warp_id; const core_config *m_config; - std::bitset<MAX_WARP_SIZE> warp_active_mask; + active_mask_t m_warp_active_mask; struct per_thread_info { per_thread_info() { diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index e3e54dc..a7b2ecf 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -259,8 +259,8 @@ void gpgpu_sim::reg_options(option_parser_t opp) "Size of shared memory per shader core (default 16kB)", "16384"); - 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", + option_parser_register(opp, "-gpgpu_shmem_warp_parts", OPT_INT32, &m_shader_config->shmem_warp_parts, + "Number of portions a warp is divided into for shared memory bank conflict check ", "2"); option_parser_register(opp, "-gpgpu_deadlock_detect", OPT_BOOL, &gpu_deadlock_detect, @@ -431,7 +431,7 @@ void gpgpu_sim::init_gpu() 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; + m_shader_config->num_shmem_bank=16; m_cluster = new simt_core_cluster*[m_shader_config->n_simt_clusters]; for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) diff --git a/src/gpgpu-sim/mem_fetch.cc b/src/gpgpu-sim/mem_fetch.cc index 74a1ac1..aa0006c 100644 --- a/src/gpgpu-sim/mem_fetch.cc +++ b/src/gpgpu-sim/mem_fetch.cc @@ -71,36 +71,30 @@ unsigned mem_fetch::sm_next_mf_request_uid=1; -mem_fetch::mem_fetch( new_addr_type addr, - unsigned data_size, - unsigned ctrl_size, - unsigned sid, - unsigned tpc, +mem_fetch::mem_fetch( const mem_access_t &access, + const warp_inst_t *inst, + unsigned ctrl_size, unsigned wid, - warp_inst_t *inst, - bool write, - partial_write_mask_t partial_write_mask, - enum mem_access_type mem_acc, - enum mf_type type, - const memory_config *config ) : m_inst() + unsigned sid, + unsigned tpc, + const class memory_config *config ) { m_request_uid = sm_next_mf_request_uid++; - - m_addr = addr; - m_data_size = data_size; + m_access = access; + if( inst ) { + m_inst = *inst; + assert( wid == m_inst.warp_id() ); + } + m_data_size = access.get_size(); m_ctrl_size = ctrl_size; m_sid = sid; - m_wid = wid; m_tpc = tpc; - if( inst ) m_inst = *inst; - m_write = write; - config->m_address_mapping.addrdec_tlx(addr,&m_raw_addr); - m_partition_addr = config->m_address_mapping.partition_address(addr); - m_mem_acc = mem_acc; - m_type = type; + m_wid = wid; + config->m_address_mapping.addrdec_tlx(access.get_addr(),&m_raw_addr); + m_partition_addr = config->m_address_mapping.partition_address(access.get_addr()); + m_type = m_access.is_write()?WR_REQ:RD_REQ; m_timestamp = gpu_sim_cycle + gpu_tot_sim_cycle; m_timestamp2 = 0; - m_status = MEM_FETCH_INITIALIZED; m_status_change = gpu_sim_cycle + gpu_tot_sim_cycle; } @@ -137,8 +131,8 @@ void mem_fetch::print( FILE *fp, bool print_inst ) const fprintf(fp," <NULL mem_fetch pointer>\n"); return; } - fprintf(fp," mf: uid=%6u, addr=0x%08llx, sid=%2u, wid=%2u, %s, partition=%u, ", - m_request_uid, m_addr, m_sid, m_wid, (m_write?"write":"read "), m_raw_addr.chip); + fprintf(fp," mf: uid=%6u, sid=%2u, partition=%u, ", m_request_uid, m_sid, m_raw_addr.chip ); + m_access.print(fp); if( (unsigned)m_status < NUM_MEM_REQ_STAT ) fprintf(fp," status = %s (%llu), ", Status_str[m_status], m_status_change ); else diff --git a/src/gpgpu-sim/mem_fetch.h b/src/gpgpu-sim/mem_fetch.h index 8fe09e0..05e2206 100644 --- a/src/gpgpu-sim/mem_fetch.h +++ b/src/gpgpu-sim/mem_fetch.h @@ -73,22 +73,8 @@ enum mf_type { RD_REQ = 0, - WT_REQ, - REPLY_DATA, // send to shader - L2_WTBK_DATA, - N_MF_TYPE -}; - -enum mem_access_type { - GLOBAL_ACC_R = 0, - LOCAL_ACC_R = 1, - CONST_ACC_R = 2, - TEXTURE_ACC_R = 3, - GLOBAL_ACC_W = 4, - LOCAL_ACC_W = 5, - L2_WRBK_ACC = 6, - INST_ACC_R = 7, - NUM_MEM_ACCESS_TYPE = 8 + WR_REQ, + REPLY_DATA // send to shader }; enum mem_fetch_status { @@ -113,23 +99,15 @@ enum mem_fetch_status { NUM_MEM_REQ_STAT }; -const unsigned partial_write_mask_bits = 128; //must be at least size of largest memory access. -typedef std::bitset<partial_write_mask_bits> partial_write_mask_t; - class mem_fetch { public: - mem_fetch( new_addr_type addr, - unsigned data_size, - unsigned ctrl_size, - unsigned sid, - unsigned tpc, - unsigned wid, - warp_inst_t *inst, - bool write, - partial_write_mask_t partial_write_mask, - enum mem_access_type mem_acc, - enum mf_type type, - const class memory_config *config ); + mem_fetch( const mem_access_t &access, + const warp_inst_t *inst, + unsigned ctrl_size, + unsigned wid, + unsigned sid, + unsigned tpc, + const class memory_config *config ); ~mem_fetch(); void set_status( enum mem_fetch_status status, unsigned long long cycle ); @@ -143,9 +121,9 @@ public: void set_data_size( unsigned size ) { m_data_size=size; } unsigned get_ctrl_size() const { return m_ctrl_size; } unsigned size() const { return m_data_size+m_ctrl_size; } - new_addr_type get_addr() const { return m_addr; } + new_addr_type get_addr() const { return m_access.get_addr(); } new_addr_type get_partition_addr() const { return m_partition_addr; } - bool get_is_write() const { return m_write; } + bool get_is_write() const { return m_access.is_write(); } unsigned get_request_uid() const { return m_request_uid; } unsigned get_sid() const { return m_sid; } unsigned get_tpc() const { return m_tpc; } @@ -154,12 +132,14 @@ public: bool isconst() const; enum mf_type get_type() const { return m_type; } bool isatomic() const; + void set_return_timestamp( unsigned t ) { m_timestamp2=t; } void set_icnt_receive_time( unsigned t ) { m_icnt_receive_time=t; } unsigned get_timestamp() const { return m_timestamp; } unsigned get_return_timestamp() const { return m_timestamp2; } unsigned get_icnt_receive_time() const { return m_icnt_receive_time; } - enum mem_access_type get_mem_acc() const { return m_mem_acc; } + + enum mem_access_type get_access_type() const { return m_access.get_type(); } address_type get_pc() const { return m_inst.empty()?-1:m_inst.pc; } const warp_inst_t &get_inst() { return m_inst; } enum mem_fetch_status get_status() const { return m_status; } @@ -176,15 +156,12 @@ private: unsigned long long m_status_change; // request type, address, size, mask - bool m_write; - enum mem_access_type m_mem_acc; - enum mf_type m_type; - new_addr_type m_addr; // linear (physical) address - new_addr_type m_partition_addr; // linear physical address *within* dram partition (partition bank select bits squeezed out) - addrdec_t m_raw_addr; // raw physical address (i.e., decoded DRAM chip-row-bank-column address) - partial_write_mask_t m_write_mask; + mem_access_t m_access; unsigned m_data_size; // how much data is being written unsigned m_ctrl_size; // how big would all this meta data be in hardware (does not necessarily match actual size of mem_fetch) + new_addr_type m_partition_addr; // linear physical address *within* dram partition (partition bank select bits squeezed out) + addrdec_t m_raw_addr; // raw physical address (i.e., decoded DRAM chip-row-bank-column address) + enum mf_type m_type; // statistics unsigned m_timestamp; // set to gpu_sim_cycle+gpu_tot_sim_cycle at struct creation diff --git a/src/gpgpu-sim/mem_latency_stat.cc b/src/gpgpu-sim/mem_latency_stat.cc index f78717e..5b4d3ac 100644 --- a/src/gpgpu-sim/mem_latency_stat.cc +++ b/src/gpgpu-sim/mem_latency_stat.cc @@ -229,7 +229,7 @@ void memory_stats_t::memlatstat_dram_access(mem_fetch *mf) } if (mf->get_pc() != (unsigned)-1) ptx_file_line_stats_add_dram_traffic(mf->get_pc(),1); - mem_access_type_stats[mf->get_mem_acc()][dram_id][bank]++; + mem_access_type_stats[mf->get_access_type()][dram_id][bank]++; } } diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 0604bb8..5c73126 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -425,17 +425,13 @@ void shader_core_ctx::fetch() 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); - mem_fetch *mf = new mem_fetch(ppc, - nbytes, + mem_access_t acc(INST_ACC_R,ppc,nbytes,false); + mem_fetch *mf = new mem_fetch(acc, + NULL/*we don't have an instruction yet*/, READ_PACKET_SIZE, + warp_id, m_sid, m_tpc, - warp_id, - NULL/*we don't have an instruction yet*/, - false, - NO_PARTIAL_WRITE, - INST_ACC_R, - RD_REQ, m_memory_config ); enum cache_request_status status = m_L1I->access( (new_addr_type)ppc, mf, gpu_sim_cycle+gpu_tot_sim_cycle ); if( status == MISS ) { @@ -481,6 +477,8 @@ void shader_core_ctx::func_exec_inst( warp_inst_t &inst ) } } } + if( inst.is_load() || inst.is_store() ) + inst.generate_mem_accesses(); } void shader_core_ctx::issue_warp( warp_inst_t *&pipe_reg, const warp_inst_t *next_inst, unsigned active_mask, unsigned warp_id ) @@ -609,51 +607,16 @@ void shader_core_ctx::execute() } } -mem_fetch *ldst_unit::create_data_mem_fetch(warp_inst_t &inst, mem_access_t &access) +mem_fetch *ldst_unit::create_data_mem_fetch(const warp_inst_t &inst, const mem_access_t &access) { - bool is_write = inst.is_store(); - mem_access_type access_type; - switch (inst.space.get_type()) { - case const_space: - case param_space_kernel: - access_type = CONST_ACC_R; - break; - case tex_space: - access_type = TEXTURE_ACC_R; - break; - case global_space: - access_type = is_write? GLOBAL_ACC_W: GLOBAL_ACC_R; - break; - case local_space: - case param_space_local: - access_type = is_write? LOCAL_ACC_W: LOCAL_ACC_R; - break; - default: assert(0); break; - } - unsigned request_size = access.req_size; - partial_write_mask_t write_mask = NO_PARTIAL_WRITE; - if (is_write) { - for (unsigned i=0;i < access.warp_indices.size();i++) { - unsigned w = access.warp_indices[i]; - int data_offset = inst.get_addr(w) & ((unsigned long long int)access.req_size - 1); - for (unsigned b = data_offset; b < data_offset + inst.data_size; b++) - write_mask.set(b); - } - } warp_inst_t inst_copy = inst; - inst_copy.set_active(access.warp_indices); - unsigned warp_id = inst.warp_id(); - mem_fetch *mf = new mem_fetch(access.addr, - request_size, - is_write?WRITE_PACKET_SIZE:READ_PACKET_SIZE, - m_sid, - m_tpc, - warp_id, - &inst_copy, - is_write, - write_mask, - access_type, - is_write?WT_REQ:RD_REQ, + inst_copy.set_active(access.get_warp_mask()); + mem_fetch *mf = new mem_fetch(access, + &inst_copy, + access.is_write()?WRITE_PACKET_SIZE:READ_PACKET_SIZE, + inst.warp_id(), + m_sid, + m_tpc, m_memory_config); return mf; } @@ -675,59 +638,51 @@ void shader_core_ctx::writeback() bool ldst_unit::shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type) { - // Process a single cycle of activity from the shared memory queue. if( inst.space.get_type() != shared_space ) return true; - - //consume port number orders from the top of the queue; - for( int i = 0; i < m_config->gpgpu_shmem_port_per_bank; i++ ) { - if (inst.accessq_empty()) - break; - unsigned current_order = inst.accessq_back().order; - //consume all requests of the same order (concurrent bank requests) - while ((!inst.accessq_empty()) && inst.accessq_back().order == current_order) - inst.accessq_pop_back(); - } - if( !inst.accessq_empty() ) { - rc_fail = BK_CONF; - fail_type = S_MEM; - m_stats->gpgpu_n_shmem_bkconflict++; - } - return inst.accessq_empty(); //done if empty. + bool stall = inst.dispatch_delay(); + if( stall ) { + fail_type = S_MEM; + rc_fail = BK_CONF; + } else + rc_fail = NO_RC_FAIL; + return !stall; } mem_stage_stall_type ldst_unit::process_memory_access_queue( cache_t *cache, warp_inst_t &inst ) { mem_stage_stall_type result = NO_RC_FAIL; - unsigned current_order = inst.accessq_back().order; - while ((!inst.accessq_empty()) && inst.accessq_back().order == current_order) { - mem_fetch *mf = create_data_mem_fetch(inst,inst.accessq_back()); - enum cache_request_status status = cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle); - if( status == HIT ) { - inst.accessq_pop_back(); - delete mf; - } else if( status == RESERVATION_FAIL ) { - result = COAL_STALL; // todo: unify enums - delete mf; - break; - } else { - assert( status == MISS || status == HIT_RESERVED ); - inst.accessq_pop_back(); - if( inst.is_load() ) { - for( unsigned r=0; r < 4; r++) - if(inst.out[r] > 0) - m_pending_writes[inst.warp_id()][inst.out[r]]++; - } - } + if( inst.accessq_empty() ) + return result; + + const mem_access_t &access = inst.accessq_back(); + mem_fetch *mf = create_data_mem_fetch(inst,inst.accessq_back()); + enum cache_request_status status = cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle); + + if ( status == HIT ) { + inst.accessq_pop_back(); + delete mf; + } else if ( status == RESERVATION_FAIL ) { + result = COAL_STALL; + delete mf; + } else { + inst.clear_active( access.get_warp_mask() ); // threads in mf writeback when mf returns + assert( status == MISS || status == HIT_RESERVED ); + inst.accessq_pop_back(); + if ( inst.is_load() ) { + for ( unsigned r=0; r < 4; r++) + if (inst.out[r] > 0) + m_pending_writes[inst.warp_id()][inst.out[r]]++; + } } - if( !inst.accessq_empty() && (inst.accessq_back().order != current_order) ) - result = BK_CONF; + if( !inst.accessq_empty() ) + result = BK_CONF; return result; } bool ldst_unit::constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type) { - if( (inst.space.get_type() != const_space) && (inst.space.get_type() != param_space_kernel) ) + if( inst.empty() || ((inst.space.get_type() != const_space) && (inst.space.get_type() != param_space_kernel)) ) return true; mem_stage_stall_type fail = process_memory_access_queue(m_L1C,inst); if (fail != NO_RC_FAIL){ @@ -742,7 +697,7 @@ bool ldst_unit::constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail bool ldst_unit::texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type) { - if( inst.space.get_type() != tex_space ) + if( inst.empty() || inst.space.get_type() != tex_space ) return true; mem_stage_stall_type fail = process_memory_access_queue(m_L1T,inst); if (fail != NO_RC_FAIL){ @@ -754,27 +709,28 @@ bool ldst_unit::texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_reason, mem_stage_access_type &access_type ) { - if( (inst.space.get_type() != global_space) && - (inst.space.get_type() != local_space) && - (inst.space.get_type() != param_space_local) ) + if( inst.empty() || + ((inst.space.get_type() != global_space) && + (inst.space.get_type() != local_space) && + (inst.space.get_type() != param_space_local)) ) return true; + assert( !inst.accessq_empty() ); mem_stage_stall_type stall_cond = NO_RC_FAIL; - unsigned current_order = inst.accessq_back().order; - while ((!inst.accessq_empty()) && inst.accessq_back().order == current_order) { - if( m_icnt->full(inst.accessq_back().req_size, inst.is_store()) ) { - stall_cond = ICNT_RC_FAIL; - break; - } else { - mem_fetch *mf = create_data_mem_fetch(inst,inst.accessq_back()); - m_icnt->push(mf); - inst.accessq_pop_back(); - if( inst.is_load() ) { - for( unsigned r=0; r < 4; r++) - if(inst.out[r] > 0) - m_pending_writes[inst.warp_id()][inst.out[r]]++; - } else if( inst.is_store() ) - m_core->inc_store_req( inst.warp_id() ); - } + const mem_access_t &access = inst.accessq_back(); + unsigned size = access.get_size(); + if( m_icnt->full(size, inst.is_store()) ) { + stall_cond = ICNT_RC_FAIL; + } else { + mem_fetch *mf = create_data_mem_fetch(inst,access); + m_icnt->push(mf); + inst.accessq_pop_back(); + inst.clear_active( access.get_warp_mask() ); + if( inst.is_load() ) { + for( unsigned r=0; r < 4; r++) + if(inst.out[r] > 0) + m_pending_writes[inst.warp_id()][inst.out[r]]++; + } else if( inst.is_store() ) + m_core->inc_store_req( inst.warp_id() ); } if( !inst.accessq_empty() ) stall_cond = COAL_STALL; @@ -785,12 +741,11 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea access_type = (iswrite)?L_MEM_ST:L_MEM_LD; else access_type = (iswrite)?G_MEM_ST:G_MEM_LD; - if (stall_cond == BK_CONF || stall_cond == COAL_STALL) - m_stats->gpgpu_n_cache_bkconflict++; } - return inst.accessq_empty(); //done if empty. + return inst.accessq_empty(); } + bool ldst_unit::response_buffer_full() const { return m_response_fifo.size() >= m_config->ldst_unit_response_queue_size; @@ -807,20 +762,6 @@ void ldst_unit::flush() // no L1D } -void ldst_unit::generate_mem_accesses(warp_inst_t &inst) -{ - // Called once per warp when warp enters ld/st unit. - // Generates a list of memory accesses, but does not perform the memory access. - if( inst.empty() ) - return; - if( inst.op == MEMORY_BARRIER_OP ) - return; - if( inst.mem_accesses_created() ) - return; - inst.get_memory_access_list(); - inst.set_mem_accesses_created(); -} - simd_function_unit::simd_function_unit( const shader_core_config *config ) { m_config=config; @@ -975,10 +916,7 @@ void ldst_unit::cycle() m_L1T->cycle(); m_L1C->cycle(); - // process new memory requests warp_inst_t &pipe_reg = *m_dispatch_reg; - generate_mem_accesses(pipe_reg); - enum mem_stage_stall_type rc_fail = NO_RC_FAIL; mem_stage_access_type type; bool done = true; @@ -1975,7 +1913,7 @@ void simt_core_cluster::icnt_inject_request_packet(class mem_fetch *mf) // stats if (mf->get_is_write()) m_stats->made_write_mfs++; else m_stats->made_read_mfs++; - switch (mf->get_mem_acc()) { + switch (mf->get_access_type()) { case CONST_ACC_R: m_stats->gpgpu_n_mem_const++; break; case TEXTURE_ACC_R: m_stats->gpgpu_n_mem_texture++; break; case GLOBAL_ACC_R: m_stats->gpgpu_n_mem_read_global++; break; @@ -1985,17 +1923,12 @@ void simt_core_cluster::icnt_inject_request_packet(class mem_fetch *mf) case INST_ACC_R: m_stats->gpgpu_n_mem_read_inst++; break; default: assert(0); } - unsigned destination = mf->get_tlx_addr().chip; mf->set_status(IN_ICNT_TO_MEM,gpu_sim_cycle+gpu_tot_sim_cycle); - if (!mf->get_is_write()) { - mf->set_type(RD_REQ); + if (!mf->get_is_write()) ::icnt_push(m_cluster_id, m_config->mem2device(destination), (void*)mf, mf->get_ctrl_size() ); - } else { - mf->set_type(WT_REQ); + else ::icnt_push(m_cluster_id, m_config->mem2device(destination), (void*)mf, mf->size()); - //gpgpu_n_sent_writes++; - } } void simt_core_cluster::icnt_cycle() @@ -2003,7 +1936,7 @@ void simt_core_cluster::icnt_cycle() if( !m_response_fifo.empty() ) { mem_fetch *mf = m_response_fifo.front(); unsigned cid = sid_to_cid(mf->get_sid()); - if( mf->get_mem_acc() == INST_ACC_R ) { + if( mf->get_access_type() == INST_ACC_R ) { // instruction fetch response if( !m_core[cid]->fetch_unit_response_buffer_full() ) { m_response_fifo.pop_front(); diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index b9e0bda..278fafc 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -105,7 +105,6 @@ #define WRITE_PACKET_SIZE 8 #define WRITE_MASK_SIZE 8 -#define NO_PARTIAL_WRITE (partial_write_mask_t()) //Set a hard limit of 32 CTAs per shader [cuda only has 8] #define MAX_CTA_PER_SHADER 32 @@ -863,15 +862,13 @@ public: void print(FILE *fout) const; private: - void generate_mem_accesses(warp_inst_t &pipe_reg); - bool shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type); bool constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type); bool texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type); bool memory_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type); mem_stage_stall_type process_memory_access_queue( cache_t *cache, warp_inst_t &inst ); - mem_fetch *create_data_mem_fetch(warp_inst_t &inst, mem_access_t &access); + mem_fetch *create_data_mem_fetch(const warp_inst_t &inst, const mem_access_t &access); const memory_config *m_memory_config; class shader_memory_interface *m_icnt; diff --git a/src/gpgpu-sim/visualizer.cc b/src/gpgpu-sim/visualizer.cc index 51348d5..730e0c9 100644 --- a/src/gpgpu-sim/visualizer.cc +++ b/src/gpgpu-sim/visualizer.cc @@ -483,7 +483,7 @@ void time_vector_print_interval2gzfile(gzFile outfile) { void time_vector_update(unsigned int uid,int slot ,long int cycle,int type) { if ( (type == RD_REQ) || (type == REPLY_DATA) ) { g_my_time_vector->update_ld( uid, slot,cycle); - } else if ( type == WT_REQ ) { + } else if ( type == WR_REQ ) { g_my_time_vector->update_st( uid, slot,cycle); } else { abort(); @@ -494,7 +494,7 @@ void check_time_vector_update(unsigned int uid,int slot ,long int latency,int ty { if ( (type == RD_REQ) || (type == REPLY_DATA) ) { g_my_time_vector->check_ld_update( uid, slot, latency ); - } else if ( type == WT_REQ ) { + } else if ( type == WR_REQ ) { g_my_time_vector->check_st_update( uid, slot, latency ); } else { abort(); |
