summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/abstract_hardware_model.h9
-rw-r--r--src/gpgpu-sim/gpu-cache.cc38
-rw-r--r--src/gpgpu-sim/gpu-cache.h81
-rw-r--r--src/gpgpu-sim/shader.cc100
-rw-r--r--src/gpgpu-sim/shader.h31
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 &reg_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;