summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/shader.cc
diff options
context:
space:
mode:
authorTor Aamodt <[email protected]>2010-11-28 20:48:33 -0800
committerTor Aamodt <[email protected]>2010-11-28 20:48:33 -0800
commit6e06c2e1de8c51a88845b7f35cea219dca7456f2 (patch)
tree28b3daed248f3f4dca9ca49f9d939f6edae10238 /src/gpgpu-sim/shader.cc
parent23d096dd1f1d4f0387087ffff0605fbf349556d2 (diff)
enabling L2 data cache... it is write through, write evict like L1.
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 8154]
Diffstat (limited to 'src/gpgpu-sim/shader.cc')
-rw-r--r--src/gpgpu-sim/shader.cc127
1 files changed, 99 insertions, 28 deletions
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 303d736..e9ec368 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -127,6 +127,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
m_thread = (thread_ctx_t*) calloc(sizeof(thread_ctx_t), config->n_thread_per_shader);
m_not_completed = 0;
+ m_active_threads.reset();
m_n_active_cta = 0;
for (unsigned i = 0; i<MAX_CTA_PER_SHADER; i++ )
m_cta_status[i]=0;
@@ -145,7 +146,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
#define STRSIZE 1024
char name[STRSIZE];
snprintf(name, STRSIZE, "L1I_%03d", m_sid);
- m_L1I = new read_only_cache( name,m_config->m_L1I_config,m_sid,get_shader_instruction_cache_id(),m_icnt);
+ m_L1I = new read_only_cache( name,m_config->m_L1I_config,m_sid,get_shader_instruction_cache_id(),m_icnt,IN_L1I_MISS_QUEUE);
m_warp.resize(m_config->max_warps_per_shader, shd_warp_t(this, warp_size));
m_pdom_warp = new pdom_warp_ctx_t*[config->max_warps_per_shader];
@@ -183,12 +184,17 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
m_fu[2] = m_ldst_unit;
m_dispatch_port[2] = ID_OC_MEM;
m_issue_port[2] = OC_EX_MEM;
+
+ m_last_inst_gpu_sim_cycle = 0;
+ m_last_inst_gpu_tot_sim_cycle = 0;
}
void shader_core_ctx::reinit(unsigned start_thread, unsigned end_thread, bool reset_not_completed )
{
- if( reset_not_completed )
+ if( reset_not_completed ) {
m_not_completed = 0;
+ m_active_threads.reset();
+ }
for (unsigned i = start_thread; i<end_thread; i++) {
m_thread[i].n_insn = 0;
m_thread[i].m_cta_id = -1;
@@ -208,14 +214,19 @@ void shader_core_ctx::init_warps( unsigned cta_id, unsigned start_thread, unsign
for (unsigned i = start_warp; i < end_warp; ++i) {
unsigned initial_active_mask = 0;
unsigned n_active=0;
+ std::bitset<MAX_WARP_SIZE> active_threads;
for (unsigned t = 0; t < m_config->warp_size; t++) {
- if ( i * m_config->warp_size + t < end_thread ) {
+ unsigned hwtid = i * m_config->warp_size + t;
+ if ( hwtid < end_thread ) {
initial_active_mask |= (1 << t);
n_active++;
+ assert( !m_active_threads.test(hwtid) );
+ m_active_threads.set( hwtid );
+ active_threads.set(t);
}
}
m_pdom_warp[i]->launch(start_pc,initial_active_mask);
- m_warp[i].init(start_pc,cta_id,i,n_active);
+ m_warp[i].init(start_pc,cta_id,i,active_threads);
m_not_completed += n_active;
}
}
@@ -509,14 +520,16 @@ void shader_core_ctx::fetch()
// and get next 1-2 instructions from i-cache...
for( unsigned i=0; i < m_config->max_warps_per_shader; i++ ) {
unsigned warp_id = (m_last_warp_fetched+1+i) % m_config->max_warps_per_shader;
- if( m_warp[warp_id].done() && !m_scoreboard->pendingWrites(warp_id) && !m_warp[warp_id].done_exit()
- && m_warp[warp_id].stores_done() && !m_warp[warp_id].inst_in_pipeline() ) {
+
+ // this code checks if this warp has finished executing and can be reclaimed
+ if( m_warp[warp_id].hardware_done() && !m_scoreboard->pendingWrites(warp_id) && !m_warp[warp_id].done_exit() ) {
bool did_exit=false;
for( unsigned t=0; t<m_config->warp_size;t++) {
unsigned tid=warp_id*m_config->warp_size+t;
if( m_thread[tid].m_functional_model_thread_state ) {
register_cta_thread_exit(tid);
m_not_completed -= 1;
+ m_active_threads.reset(tid);
m_thread[tid].m_functional_model_thread_state=NULL;
did_exit=true;
}
@@ -524,7 +537,9 @@ void shader_core_ctx::fetch()
if( did_exit )
m_warp[warp_id].set_done_exit();
}
- if( !m_warp[warp_id].done() && !m_warp[warp_id].imiss_pending() && m_warp[warp_id].ibuffer_empty() ) {
+
+ // this code fetches instructions from the i-cache or generates memory requests
+ if( !m_warp[warp_id].functional_done() && !m_warp[warp_id].imiss_pending() && m_warp[warp_id].ibuffer_empty() ) {
address_type pc = m_warp[warp_id].get_pc();
address_type ppc = pc + PROGRAM_MEM_START;
unsigned nbytes=16;
@@ -542,7 +557,8 @@ void shader_core_ctx::fetch()
m_sid,
m_tpc,
m_memory_config );
- enum cache_request_status status = m_L1I->access( (new_addr_type)ppc, mf, gpu_sim_cycle+gpu_tot_sim_cycle );
+ std::list<cache_event> events;
+ enum cache_request_status status = m_L1I->access( (new_addr_type)ppc, mf, gpu_sim_cycle+gpu_tot_sim_cycle,events);
if( status == MISS ) {
m_last_warp_fetched=warp_id;
m_warp[warp_id].set_imiss_pending();
@@ -551,6 +567,7 @@ void shader_core_ctx::fetch()
m_last_warp_fetched=warp_id;
m_inst_fetch_buffer = ifetch_buffer_t(pc,nbytes,warp_id);
m_warp[warp_id].set_last_fetch(gpu_sim_cycle);
+ delete mf;
} else {
assert( status == RESERVATION_FAIL );
delete mf;
@@ -581,7 +598,7 @@ void shader_core_ctx::func_exec_inst( warp_inst_t &inst )
inst.set_addr(t, translate_local_memaddr(inst.get_addr(t), tid,
m_config->n_simt_clusters*m_config->n_simt_cores_per_cluster) );
if ( ptx_thread_done(tid) ) {
- m_warp[inst.warp_id()].inc_n_completed();
+ m_warp[inst.warp_id()].set_completed(t);
m_warp[inst.warp_id()].ibuffer_flush();
}
}
@@ -748,6 +765,8 @@ void shader_core_ctx::writeback()
m_stats->m_num_sim_insn[m_sid]++;
m_gpu->gpu_sim_insn_last_update_sid = m_sid;
m_gpu->gpu_sim_insn_last_update = gpu_sim_cycle;
+ m_last_inst_gpu_sim_cycle = gpu_sim_cycle;
+ m_last_inst_gpu_tot_sim_cycle = gpu_tot_sim_cycle;
m_gpu->gpu_sim_insn += pipe_reg->active_count();
pipe_reg->clear();
}
@@ -775,24 +794,32 @@ mem_stage_stall_type ldst_unit::process_memory_access_queue( cache_t *cache, war
const mem_access_t &access = inst.accessq_back();
mem_fetch *mf = m_mf_allocator->alloc(inst,inst.accessq_back());
- enum cache_request_status status = cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle);
+ 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 )
+ m_core->inc_store_req( inst.warp_id() );
if ( status == HIT ) {
+ assert( !read_sent );
inst.accessq_pop_back();
- delete mf;
+ if( !write_sent )
+ delete mf;
} else if ( status == RESERVATION_FAIL ) {
result = COAL_STALL;
+ assert( !read_sent );
+ assert( !write_sent );
delete mf;
} else {
- inst.clear_active( access.get_warp_mask() ); // threads in mf writeback when mf returns
assert( status == MISS || status == HIT_RESERVED );
+ inst.clear_active( access.get_warp_mask() ); // threads in mf writeback when mf returns
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() );
+ }
}
if( !inst.accessq_empty() )
result = BK_CONF;
@@ -951,15 +978,17 @@ ldst_unit::ldst_unit( shader_memory_interface *icnt,
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);
- m_L1C = new read_only_cache(L1C_name,m_config->m_L1C_config,m_sid,get_shader_constant_cache_id(),icnt);
+ 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 data_cache(L1D_name,m_config->m_L1D_config,m_sid,get_shader_normal_cache_id(),m_icnt,m_mf_allocator);
+ m_L1D = new data_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;
m_next_global=NULL;
+ m_last_inst_gpu_sim_cycle=0;
+ m_last_inst_gpu_tot_sim_cycle=0;
}
void ldst_unit::writeback()
@@ -984,6 +1013,8 @@ void ldst_unit::writeback()
}
}
m_next_wb.clear();
+ m_last_inst_gpu_sim_cycle = gpu_sim_cycle;
+ m_last_inst_gpu_tot_sim_cycle = gpu_tot_sim_cycle;
}
}
@@ -1046,7 +1077,6 @@ void ldst_unit::cycle()
if( !m_response_fifo.empty() ) {
mem_fetch *mf = m_response_fifo.front();
if (mf->istexture()) {
- mf->set_status(IN_SHADER_FETCHED,gpu_sim_cycle+gpu_tot_sim_cycle);
m_L1T->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle);
m_response_fifo.pop_front();
} else if (mf->isconst()) {
@@ -1054,11 +1084,12 @@ void ldst_unit::cycle()
m_L1C->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle);
m_response_fifo.pop_front();
} else {
- if( mf->get_is_write() ) {
+ if( mf->get_type() == WRITE_ACK ) {
m_core->store_ack(mf);
m_response_fifo.pop_front();
delete mf;
} else {
+ assert( !mf->get_is_write() ); // L1 cache is write evict, allocate line on load miss only
if( mf->get_inst().cache_op != CACHE_GLOBAL && m_L1D ) {
m_L1D->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle);
m_response_fifo.pop_front();
@@ -1247,10 +1278,10 @@ void shader_core_ctx::print_stage(unsigned int stage, FILE *fout ) const
m_pipeline_reg[stage]->print(fout);
}
-void shader_core_ctx::display_pdom_state(FILE *fout, int mask ) const
+void shader_core_ctx::display_simt_state(FILE *fout, int mask ) const
{
if ( (mask & 4) && m_config->model == POST_DOMINATOR ) {
- fprintf(fout,"warp status:\n");
+ fprintf(fout,"per warp SIMT control-flow state:\n");
unsigned n = m_config->n_thread_per_shader / m_config->warp_size;
for (unsigned i=0; i < n; i++) {
unsigned nactive = 0;
@@ -1294,6 +1325,8 @@ void ldst_unit::print(FILE *fout) const
}
fprintf(fout,"LD/ST wb = ");
m_next_wb.print(fout);
+ fprintf(fout, "Last LD/ST writeback @ %llu + %llu (gpu_sim_cycle+gpu_tot_sim_cycle)\n",
+ m_last_inst_gpu_sim_cycle, m_last_inst_gpu_tot_sim_cycle );
fprintf(fout,"Pending register writes:\n");
std::map<unsigned/*warp_id*/, std::map<unsigned/*regnum*/,unsigned/*count*/> >::const_iterator w;
for( w=m_pending_writes.begin(); w!=m_pending_writes.end(); w++ ) {
@@ -1325,7 +1358,7 @@ void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, int mask ) con
gpu_tot_sim_cycle, gpu_sim_cycle, m_not_completed);
fprintf(fout, "=================================================\n");
- dump_istream_state(fout);
+ dump_warp_state(fout);
fprintf(fout,"\n");
m_L1I->display_state(fout);
@@ -1345,7 +1378,7 @@ void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, int mask ) con
m_warp[i].print_ibuffer(fout);
}
fprintf(fout,"\n");
- display_pdom_state(fout,mask);
+ display_simt_state(fout,mask);
m_scoreboard->printContents();
@@ -1371,6 +1404,24 @@ void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, int mask ) con
fprintf(fout, "EX/WB = ");
print_stage(EX_WB, fout);
fprintf(fout, "\n");
+ fprintf(fout, "Last EX/WB writeback @ %llu + %llu (gpu_sim_cycle+gpu_tot_sim_cycle)\n",
+ m_last_inst_gpu_sim_cycle, m_last_inst_gpu_tot_sim_cycle );
+
+ if( m_active_threads.count() <= 2*m_config->warp_size ) {
+ fprintf(fout,"Active Threads : ");
+ unsigned last_warp_id = -1;
+ for(unsigned tid=0; tid < m_active_threads.size(); tid++ ) {
+ unsigned warp_id = tid/m_config->warp_size;
+ if( m_active_threads.test(tid) ) {
+ if( warp_id != last_warp_id ) {
+ fprintf(fout,"\n warp %u : ", warp_id );
+ last_warp_id=warp_id;
+ }
+ fprintf(fout,"%u ", tid );
+ }
+ }
+ }
+
}
unsigned int shader_core_config::max_cta( const kernel_info_t &k ) const
@@ -1679,18 +1730,24 @@ void shader_core_ctx::accept_ldst_unit_response(mem_fetch * mf)
void shader_core_ctx::store_ack( class mem_fetch *mf )
{
+ assert( mf->get_type() == WRITE_ACK );
unsigned warp_id = mf->get_wid();
m_warp[warp_id].dec_store_req();
}
-bool shd_warp_t::done()
+bool shd_warp_t::functional_done() const
{
return get_n_completed() == m_warp_size;
}
+bool shd_warp_t::hardware_done() const
+{
+ return functional_done() && stores_done() && !inst_in_pipeline();
+}
+
bool shd_warp_t::waiting()
{
- if ( done() ) {
+ if ( functional_done() ) {
// waiting to be initialized with a kernel
return true;
} else if ( m_shader->warp_waiting_at_barrier(m_warp_id) ) {
@@ -1712,10 +1769,14 @@ bool shd_warp_t::waiting()
void shd_warp_t::print( FILE *fout ) const
{
- if ( n_completed < m_warp_size ) {
- fprintf( fout, "w%02u npc: 0x%04x, done:%2u i:%u s:%u a:%u (done: ",
+ if( !done_exit() ) {
+ fprintf( fout, "w%02u npc: 0x%04x, done:%c%c%c%c:%2u i:%u s:%u a:%u (done: ",
m_warp_id,
m_next_pc,
+ (functional_done()?'f':' '),
+ (stores_done()?'s':' '),
+ (inst_in_pipeline()?' ':'i'),
+ (done_exit()?'e':' '),
n_completed,
m_inst_in_pipeline,
m_stores_outstanding,
@@ -1727,6 +1788,7 @@ void shd_warp_t::print( FILE *fout ) const
fprintf(fout,",");
}
fprintf(fout,") ");
+ fprintf(fout," active=%s", m_active_threads.to_string().c_str() );
fprintf(fout," last fetched @ %5llu", m_last_fetch);
if( m_imiss_pending )
fprintf(fout," i-miss pending");
@@ -2023,6 +2085,15 @@ unsigned simt_core_cluster::get_not_completed() const
return not_completed;
}
+void simt_core_cluster::print_not_completed( FILE *fp ) const
+{
+ for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) {
+ unsigned not_completed=m_core[i]->get_not_completed();
+ unsigned sid=m_config->cid_to_sid(i,m_cluster_id);
+ fprintf(fp,"%u(%u) ", sid, not_completed );
+ }
+}
+
unsigned simt_core_cluster::get_n_active_cta() const
{
unsigned n=0;
@@ -2109,7 +2180,7 @@ void simt_core_cluster::icnt_cycle()
if (!mf)
return;
assert(mf->get_tpc() == m_cluster_id);
- assert(mf->get_type() == REPLY_DATA);
+ assert(mf->get_type() == READ_REPLY || mf->get_type() == WRITE_ACK );
mf->set_status(IN_CLUSTER_TO_SHADER_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
//m_memory_stats->memlatstat_read_done(mf,m_shader_config->max_warps_per_shader);
m_response_fifo.push_back(mf);