From c591d13a90aad7d99bb40aef9e44d6bfce0b74c0 Mon Sep 17 00:00:00 2001 From: Tim Rogers Date: Sun, 10 Feb 2013 20:40:34 -0800 Subject: Merging //depot/gpgpu_sim_research/fermi_locality/... to //depot/gpgpu_sim_research/fermi/... Adding in some protected constructors to the core cache classes. This allows us to customize caches (for example having them use a custom tag array) more easily. Also I made the in-class tag_array object in the baseline_cache into a pointer. This allows derived classes to easily create custom tag arrays. I think in general, class extendibility is increased when pointers are used instead of in-object storage. [git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 15223] --- src/gpgpu-sim/gpu-cache.cc | 38 ++++++++--------- src/gpgpu-sim/gpu-cache.h | 81 +++++++++++++++++++++++++++++++++--- src/gpgpu-sim/shader.cc | 100 +++++++++++++++++++++++++++++++++++++-------- src/gpgpu-sim/shader.h | 31 +++++++++++++- 4 files changed, 208 insertions(+), 42 deletions(-) (limited to 'src/gpgpu-sim') diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index 49c7991..2334bf7 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -347,15 +347,15 @@ void baseline_cache::fill(mem_fetch *mf, unsigned time){ assert( e->second.m_valid ); mf->set_data_size( e->second.m_data_size ); if ( m_config.m_alloc_policy == ON_MISS ) - m_tag_array.fill(e->second.m_cache_index,time); + m_tag_array->fill(e->second.m_cache_index,time); else if ( m_config.m_alloc_policy == ON_FILL ) - m_tag_array.fill(e->second.m_block_addr,time); + m_tag_array->fill(e->second.m_block_addr,time); else abort(); bool has_atomic = false; m_mshrs.mark_ready(e->second.m_block_addr, has_atomic); if (has_atomic) { assert(m_config.m_alloc_policy == ON_MISS); - cache_block_t &block = m_tag_array.get_block(e->second.m_cache_index); + cache_block_t &block = m_tag_array->get_block(e->second.m_cache_index); block.m_status = MODIFIED; // mark line as dirty for atomic operation } m_extra_mf_fields.erase(mf); @@ -369,7 +369,7 @@ bool baseline_cache::waiting_for_fill( mem_fetch *mf ){ void baseline_cache::print(FILE *fp, unsigned &accesses, unsigned &misses) const{ fprintf( fp, "Cache %s:\t", m_name.c_str() ); - m_tag_array.print(fp,accesses,misses); + m_tag_array->print(fp,accesses,misses); } void baseline_cache::display_state( FILE *fp ) const{ @@ -395,17 +395,17 @@ void baseline_cache::send_read_request(new_addr_type addr, new_addr_type block_a bool mshr_avail = !m_mshrs.full(block_addr); if ( mshr_hit && mshr_avail ) { if(read_only) - m_tag_array.access(block_addr,time,cache_index); + m_tag_array->access(block_addr,time,cache_index); else - m_tag_array.access(block_addr,time,cache_index,wb,evicted); + m_tag_array->access(block_addr,time,cache_index,wb,evicted); m_mshrs.add(block_addr,mf); do_miss = true; } else if ( !mshr_hit && mshr_avail && (m_miss_queue.size() < m_config.m_miss_queue_size) ) { if(read_only) - m_tag_array.access(block_addr,time,cache_index); + m_tag_array->access(block_addr,time,cache_index); else - m_tag_array.access(block_addr,time,cache_index,wb,evicted); + m_tag_array->access(block_addr,time,cache_index,wb,evicted); m_mshrs.add(block_addr,mf); m_extra_mf_fields[mf] = extra_mf_fields(block_addr,cache_index, mf->get_data_size()); @@ -432,8 +432,8 @@ void data_cache::send_write_request(mem_fetch *mf, cache_event request, unsigned /// Write-back hit: Mark block as modified cache_request_status data_cache::wr_hit_wb(new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, std::list &events, enum cache_request_status status ){ new_addr_type block_addr = m_config.block_addr(addr); - m_tag_array.access(block_addr,time,cache_index); // update LRU state - cache_block_t &block = m_tag_array.get_block(cache_index); + m_tag_array->access(block_addr,time,cache_index); // update LRU state + cache_block_t &block = m_tag_array->get_block(cache_index); block.m_status = MODIFIED; m_write_access++; @@ -446,8 +446,8 @@ cache_request_status data_cache::wr_hit_wt(new_addr_type addr, unsigned cache_in return RESERVATION_FAIL; // cannot handle request this cycle new_addr_type block_addr = m_config.block_addr(addr); - m_tag_array.access(block_addr,time,cache_index); // update LRU state - cache_block_t &block = m_tag_array.get_block(cache_index); + m_tag_array->access(block_addr,time,cache_index); // update LRU state + cache_block_t &block = m_tag_array->get_block(cache_index); block.m_status = MODIFIED; // generate a write-through @@ -463,7 +463,7 @@ cache_request_status data_cache::wr_hit_we(new_addr_type addr, unsigned cache_in return RESERVATION_FAIL; // cannot handle request this cycle // generate a write-through/evict - cache_block_t &block = m_tag_array.get_block(cache_index); + cache_block_t &block = m_tag_array->get_block(cache_index); send_write_request(mf, WRITE_REQUEST_SENT, time, events); // Invalidate block @@ -555,10 +555,10 @@ enum cache_request_status data_cache::wr_miss_no_wa(new_addr_type addr, unsigned /// Baseline read hit: Update LRU status of block. Special case for atomic instructions -> Mark block as modified enum cache_request_status data_cache::rd_hit_base(new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, std::list &events, enum cache_request_status status ){ new_addr_type block_addr = m_config.block_addr(addr); - m_tag_array.access(block_addr,time,cache_index); + m_tag_array->access(block_addr,time,cache_index); if(mf->isatomic()){ // Atomics treated as global read/write requests - Perform read, mark line as MODIFIED assert(mf->get_access_type() == GLOBAL_ACC_R); - cache_block_t &block = m_tag_array.get_block(cache_index); + cache_block_t &block = m_tag_array->get_block(cache_index); block.m_status = MODIFIED; // mark line as dirty } @@ -598,9 +598,9 @@ enum cache_request_status read_only_cache::access( new_addr_type addr, mem_fetch assert(!mf->get_is_write()); new_addr_type block_addr = m_config.block_addr(addr); unsigned cache_index = (unsigned)-1; - enum cache_request_status status = m_tag_array.probe(block_addr,cache_index); + enum cache_request_status status = m_tag_array->probe(block_addr,cache_index); if ( status == HIT ) { - m_tag_array.access(block_addr,time,cache_index); // update LRU state + m_tag_array->access(block_addr,time,cache_index); // update LRU state return HIT; }else if ( status != RESERVATION_FAIL ) { if(!miss_queue_full(0)){ @@ -622,7 +622,7 @@ enum cache_request_status l1_cache::access( new_addr_type addr, mem_fetch *mf, u bool wr = mf->get_is_write(); new_addr_type block_addr = m_config.block_addr(addr); unsigned cache_index = (unsigned)-1; - enum cache_request_status status = m_tag_array.probe(block_addr,cache_index); + enum cache_request_status status = m_tag_array->probe(block_addr,cache_index); // Each function pointer ( m_[rd/wr]_[hit/miss] ) is set in the data_cache constructor to reflect the corresponding cache configuration options. // Function pointers were used to avoid many long conditional branches resulting from many cache configuration options. @@ -650,7 +650,7 @@ enum cache_request_status l2_cache::access( new_addr_type addr, mem_fetch *mf, u bool wr = mf->get_is_write(); new_addr_type block_addr = m_config.block_addr(addr); unsigned cache_index = (unsigned)-1; - enum cache_request_status status = m_tag_array.probe(block_addr,cache_index); + enum cache_request_status status = m_tag_array->probe(block_addr,cache_index); // Each function pointer ( m_[rd/wr]_[hit/miss] ) is set in the data_cache constructor to reflect the corresponding cache configuration options. // Function pointers were used to avoid many long conditional branches resulting from many cache configuration options. diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index dabcc18..fb59c01 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -394,7 +394,15 @@ class baseline_cache : public cache_t { public: baseline_cache( const char *name, const cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, enum mem_fetch_status status ) - : m_config(config), m_tag_array(config,core_id,type_id), m_mshrs(config.m_mshr_entries,config.m_mshr_max_merge) + : m_config(config), m_tag_array(new tag_array(config,core_id,type_id)), m_mshrs(config.m_mshr_entries,config.m_mshr_max_merge) + { + init( name, config, memport, status ); + } + + void init( const char *name, + const cache_config &config, + mem_fetch_interface *memport, + enum mem_fetch_status status ) { m_name = name; assert(config.m_mshr_type == ASSOC); @@ -407,6 +415,11 @@ public: n_simt_to_mem=0; } + virtual ~baseline_cache() + { + delete m_tag_array; + } + virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list &events ) = 0; /// Sends next request to lower level of memory void cycle(); @@ -419,7 +432,7 @@ public: /// Pop next ready access (does not include accesses that "HIT") mem_fetch *next_access(){return m_mshrs.next_access();} // flash invalidate all entries in cache - void flush(){m_tag_array.flush();} + void flush(){m_tag_array->flush();} void print(FILE *fp, unsigned &accesses, unsigned &misses) const; void display_state( FILE *fp ) const; @@ -431,17 +444,33 @@ public: } void get_stats(unsigned &accesses, unsigned &misses) const { - m_tag_array.get_stats(accesses, misses); + m_tag_array->get_stats(accesses, misses); } void set_icnt_power_stats(unsigned &simt_to_mem) const{ simt_to_mem = n_simt_to_mem; } - protected: +protected: + // Constructor that can be used by derived classes with custom tag arrays + baseline_cache( const char *name, + const cache_config &config, + int core_id, + int type_id, + mem_fetch_interface *memport, + enum mem_fetch_status status, + tag_array* new_tag_array ) + : m_config(config), + m_tag_array( new_tag_array ), + m_mshrs(config.m_mshr_entries,config.m_mshr_max_merge) + { + init( name, config, memport, status ); + } + +protected: std::string m_name; const cache_config &m_config; - tag_array m_tag_array; + tag_array* m_tag_array; mshr_table m_mshrs; std::list m_miss_queue; enum mem_fetch_status m_miss_queue_status; @@ -494,6 +523,12 @@ public: /// Access cache for read_only_cache: returns RESERVATION_FAIL if request could not be accepted (for any reason) virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list &events ); + + virtual ~read_only_cache(){} + +protected: + read_only_cache( const char *name, const cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, enum mem_fetch_status status, tag_array* new_tag_array ) + : baseline_cache(name,config,core_id,type_id,memport,status, new_tag_array){} }; /// Data cache - Implements common functions for L1 and L2 data cache @@ -503,6 +538,13 @@ public: int core_id, int type_id, mem_fetch_interface *memport, mem_fetch_allocator *mfcreator, enum mem_fetch_status status ) : baseline_cache(name,config,core_id,type_id,memport,status) + { + init( mfcreator ); + } + + virtual ~data_cache() {} + + void init( mem_fetch_allocator *mfcreator ) { m_memfetch_creator=mfcreator; @@ -530,6 +572,20 @@ public: } } +protected: + data_cache( const char *name, + const cache_config &config, + int core_id, + int type_id, + mem_fetch_interface *memport, + mem_fetch_allocator *mfcreator, + enum mem_fetch_status status, + tag_array* new_tag_array ) + : baseline_cache(name, config, core_id, type_id, memport,status, new_tag_array) + { + init( mfcreator ); + } + protected: mem_fetch_allocator *m_memfetch_creator; @@ -576,8 +632,21 @@ public: mem_fetch_allocator *mfcreator, enum mem_fetch_status status ) : data_cache(name,config,core_id,type_id,memport,mfcreator,status){} + virtual ~l1_cache(){} + virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list &events ); +protected: + l1_cache( const char *name, + const cache_config &config, + int core_id, + int type_id, + mem_fetch_interface *memport, + mem_fetch_allocator *mfcreator, + enum mem_fetch_status status, + tag_array* new_tag_array ) + : data_cache(name,config,core_id,type_id,memport,mfcreator,status, new_tag_array){} + }; /// Models second level shared cache with global write-back and write-allocate policies @@ -588,6 +657,8 @@ public: mem_fetch_allocator *mfcreator, enum mem_fetch_status status ) : data_cache(name,config,core_id,type_id,memport,mfcreator,status){} + virtual ~l2_cache() {} + virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list &events ); }; diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 8573344..7a822b2 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -607,7 +607,7 @@ void shader_core_ctx::issue_warp( register_set& pipe_reg_set, const warp_inst_t* m_warp[warp_id].ibuffer_free(); assert(next_inst->valid()); **pipe_reg = *next_inst; // static instruction information - (*pipe_reg)->issue( active_mask, warp_id, gpu_tot_sim_cycle + gpu_sim_cycle ); // dynamic instruction information + (*pipe_reg)->issue( active_mask, warp_id, gpu_tot_sim_cycle + gpu_sim_cycle, m_warp[warp_id].get_dynamic_warp_id() ); // dynamic instruction information m_stats->shader_cycle_distro[2+(*pipe_reg)->active_count()]++; func_exec_inst( **pipe_reg ); if( next_inst->op == BARRIER_OP ) @@ -1093,17 +1093,15 @@ bool ldst_unit::shared_cycle( warp_inst_t &inst, mem_stage_stall_type &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 +ldst_unit::process_cache_access( cache_t* cache, + new_addr_type address, + warp_inst_t &inst, + std::list& events, + mem_fetch *mf, + enum cache_request_status status ) { mem_stage_stall_type result = NO_RC_FAIL; - if( inst.accessq_empty() ) - return result; - - //const mem_access_t &access = inst.accessq_back(); - mem_fetch *mf = m_mf_allocator->alloc(inst,inst.accessq_back()); - std::list events; - enum cache_request_status status = cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle,events); - bool write_sent = was_write_sent(events); bool read_sent = was_read_sent(events); if( write_sent ) @@ -1133,6 +1131,19 @@ mem_stage_stall_type ldst_unit::process_memory_access_queue( cache_t *cache, war return result; } +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; + if( inst.accessq_empty() ) + return result; + + //const mem_access_t &access = inst.accessq_back(); + mem_fetch *mf = m_mf_allocator->alloc(inst,inst.accessq_back()); + std::list events; + enum cache_request_status status = cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle,events); + return process_cache_access( cache, mf->get_addr(), inst, events, mf, status ); +} + bool ldst_unit::constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type) { if( inst.empty() || ((inst.space.get_type() != const_space) && (inst.space.get_type() != param_space_kernel)) ) @@ -1319,8 +1330,7 @@ void pipelined_simd_unit::issue( register_set& source_reg ) } */ - -ldst_unit::ldst_unit( mem_fetch_interface *icnt, +void ldst_unit::init( mem_fetch_interface *icnt, shader_core_mem_fetch_allocator *mf_allocator, shader_core_ctx *core, opndcoll_rfu_t *operand_collector, @@ -1329,7 +1339,7 @@ ldst_unit::ldst_unit( mem_fetch_interface *icnt, const memory_config *mem_config, shader_core_stats *stats, unsigned sid, - unsigned tpc ) : pipelined_simd_unit(NULL,config,3,core), m_next_wb(config) + unsigned tpc ) { m_memory_config = mem_config; m_icnt = icnt; @@ -1343,15 +1353,11 @@ ldst_unit::ldst_unit( mem_fetch_interface *icnt, #define STRSIZE 1024 char L1T_name[STRSIZE]; char L1C_name[STRSIZE]; - char L1D_name[STRSIZE]; snprintf(L1T_name, STRSIZE, "L1T_%03d", m_sid); snprintf(L1C_name, STRSIZE, "L1C_%03d", m_sid); - snprintf(L1D_name, STRSIZE, "L1D_%03d", m_sid); m_L1T = new tex_cache(L1T_name,m_config->m_L1T_config,m_sid,get_shader_texture_cache_id(),icnt,IN_L1T_MISS_QUEUE,IN_SHADER_L1T_ROB); m_L1C = new read_only_cache(L1C_name,m_config->m_L1C_config,m_sid,get_shader_constant_cache_id(),icnt,IN_L1C_MISS_QUEUE); m_L1D = NULL; - if( !m_config->m_L1D_config.disabled() ) - m_L1D = new l1_cache(L1D_name,m_config->m_L1D_config,m_sid,get_shader_normal_cache_id(),m_icnt,m_mf_allocator,IN_L1D_MISS_QUEUE); m_mem_rc = NO_RC_FAIL; m_num_writeback_clients=5; // = shared memory, global/local (uncached), L1D, L1T, L1C m_writeback_arb = 0; @@ -1361,6 +1367,66 @@ ldst_unit::ldst_unit( mem_fetch_interface *icnt, m_last_inst_gpu_tot_sim_cycle=0; } + +ldst_unit::ldst_unit( mem_fetch_interface *icnt, + shader_core_mem_fetch_allocator *mf_allocator, + shader_core_ctx *core, + opndcoll_rfu_t *operand_collector, + Scoreboard *scoreboard, + const shader_core_config *config, + const memory_config *mem_config, + shader_core_stats *stats, + unsigned sid, + unsigned tpc ) : pipelined_simd_unit(NULL,config,3,core), m_next_wb(config) +{ + init( icnt, + mf_allocator, + core, + operand_collector, + scoreboard, + config, + mem_config, + stats, + sid, + tpc ); + if( !m_config->m_L1D_config.disabled() ) { + char L1D_name[STRSIZE]; + snprintf(L1D_name, STRSIZE, "L1D_%03d", m_sid); + m_L1D = new l1_cache( L1D_name, + m_config->m_L1D_config, + m_sid, + get_shader_normal_cache_id(), + m_icnt, + m_mf_allocator, + IN_L1D_MISS_QUEUE ); + } +} + +ldst_unit::ldst_unit( mem_fetch_interface *icnt, + shader_core_mem_fetch_allocator *mf_allocator, + shader_core_ctx *core, + opndcoll_rfu_t *operand_collector, + Scoreboard *scoreboard, + const shader_core_config *config, + const memory_config *mem_config, + shader_core_stats *stats, + unsigned sid, + unsigned tpc, + l1_cache* new_l1d_cache ) + : pipelined_simd_unit(NULL,config,3,core), m_L1D(new_l1d_cache), m_next_wb(config) +{ + init( icnt, + mf_allocator, + core, + operand_collector, + scoreboard, + config, + mem_config, + stats, + sid, + tpc ); +} + void ldst_unit:: issue( register_set ®_set ) { warp_inst_t* inst = *(reg_set.get_ready()); diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 6be54fb..c74fa96 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -965,12 +965,41 @@ public: void set_icnt_power_stats(unsigned &simt_to_mem) const; -private: +protected: + ldst_unit( mem_fetch_interface *icnt, + shader_core_mem_fetch_allocator *mf_allocator, + shader_core_ctx *core, + opndcoll_rfu_t *operand_collector, + Scoreboard *scoreboard, + const shader_core_config *config, + const memory_config *mem_config, + shader_core_stats *stats, + unsigned sid, + unsigned tpc, + l1_cache* new_l1d_cache ); + void init( mem_fetch_interface *icnt, + shader_core_mem_fetch_allocator *mf_allocator, + shader_core_ctx *core, + opndcoll_rfu_t *operand_collector, + Scoreboard *scoreboard, + const shader_core_config *config, + const memory_config *mem_config, + shader_core_stats *stats, + unsigned sid, + unsigned tpc ); + +protected: 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); + virtual mem_stage_stall_type process_cache_access( cache_t* cache, + new_addr_type address, + warp_inst_t &inst, + std::list& events, + mem_fetch *mf, + enum cache_request_status status ); mem_stage_stall_type process_memory_access_queue( cache_t *cache, warp_inst_t &inst ); const memory_config *m_memory_config; -- cgit v1.3