diff options
| author | Tim Rogers <[email protected]> | 2013-02-10 20:40:34 -0800 |
|---|---|---|
| committer | Andrew Boktor <[email protected]> | 2014-08-14 13:50:04 -0700 |
| commit | c591d13a90aad7d99bb40aef9e44d6bfce0b74c0 (patch) | |
| tree | 1525326dfa44a4d7f28596bbbfdd6e7892a30088 | |
| parent | e4d7bf562e8e90fa4523efc186322bff416c0506 (diff) | |
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]
| -rw-r--r-- | src/abstract_hardware_model.h | 9 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-cache.cc | 38 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-cache.h | 81 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 100 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.h | 31 |
5 files changed, 216 insertions, 43 deletions
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index cc7a4b7..ce428da 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -769,12 +769,13 @@ public: { m_empty=true; } - void issue( const active_mask_t &mask, unsigned warp_id, unsigned long long cycle ) + void issue( const active_mask_t &mask, unsigned warp_id, unsigned long long cycle, int dynamic_warp_id ) { m_warp_active_mask = mask; m_warp_issued_mask = mask; m_uid = ++sm_next_uid; m_warp_id = warp_id; + m_dynamic_warp_id = dynamic_warp_id; issue_cycle = cycle; cycles = initiation_interval; m_cache_hit=false; @@ -857,6 +858,11 @@ public: assert( !m_empty ); return m_warp_id; } + unsigned dynamic_warp_id() const + { + assert( !m_empty ); + return m_dynamic_warp_id; + } bool has_callback( unsigned n ) const { return m_warp_active_mask[n] && m_per_scalar_thread_valid && @@ -901,6 +907,7 @@ protected: bool m_isatomic; bool m_is_printf; unsigned m_warp_id; + unsigned m_dynamic_warp_id; const core_config *m_config; active_mask_t m_warp_active_mask; // dynamic active mask for timing model (after predication) active_mask_t m_warp_issued_mask; // active mask at issue (prior to predication test) -- for instruction counting 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<cache_event> &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<cache_event> &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<cache_event> &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<mem_fetch*> 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<cache_event> &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 @@ -504,6 +539,13 @@ public: 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; // Set read hit function @@ -531,6 +573,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; // Functions for data cache access @@ -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<cache_event> &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<cache_event> &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<cache_event>& 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<cache_event> 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<cache_event> 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<cache_event>& 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; |
