diff options
| author | Tor Aamodt <[email protected]> | 2010-11-30 02:15:16 -0800 |
|---|---|---|
| committer | Tor Aamodt <[email protected]> | 2010-11-30 02:15:16 -0800 |
| commit | 52a638e84693fff528defbcbd24ecb58216baaba (patch) | |
| tree | 34449df36f63267119cd048508810a101618fd39 | |
| parent | 7a47f9cd62902d960a989a920d882f3b77fe7b2a (diff) | |
integrate changes (makes code more modular, i would argue)
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 8179]
| -rw-r--r-- | src/abstract_hardware_model.h | 3 | ||||
| -rw-r--r-- | src/cuda-sim/cuda-sim.cc | 37 | ||||
| -rw-r--r-- | src/cuda-sim/cuda-sim.h | 5 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_ir.cc | 4 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 161 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.h | 11 |
6 files changed, 133 insertions, 88 deletions
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 3b197ab..c519be1 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -532,6 +532,7 @@ public: { m_decoded=false; pc=(address_type)-1; + reconvergence_pc=(address_type)-1; op=NO_OP; memset(out, 0, sizeof(unsigned)); memset(in, 0, sizeof(unsigned)); @@ -557,6 +558,8 @@ public: unsigned isize; // size of instruction in bytes op_type op; // opcode (uarch visible) _memory_op_t memory_op; // memory_op used by ptxplus + + address_type reconvergence_pc; // -1 => not a branch, -2 => use function return address unsigned out[4]; unsigned in[4]; diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 34bfe82..4326987 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -96,6 +96,8 @@ addr_t g_debug_pc = 0xBEEF1518; unsigned g_ptx_sim_num_insn = 0; unsigned gpgpu_param_num_shaders = 0; +static address_type get_converge_point(address_type pc); + void gpgpu_t::gpgpu_ptx_sim_bindNameToTexture(const char* name, const struct textureReference* texref) { std::string texname(name); @@ -242,13 +244,10 @@ void function_info::ptx_assemble() target.set_type(label_t); } } - for ( unsigned ii=0; ii < n; ii += m_instr_mem[ii]->inst_size() ) { // handle branch instructions - ptx_instruction *pI = m_instr_mem[ii]; - pI->pre_decode(); - } printf(" done.\n"); fflush(stdout); + printf("GPGPU-Sim PTX: finding reconvergence points for \'%s\'...\n", m_name.c_str() ); create_basic_blocks(); connect_basic_blocks(); @@ -274,6 +273,14 @@ void function_info::ptx_assemble() print_ipostdominators(); } + printf("GPGPU-Sim PTX: pre-decoding instructions for \'%s\'... ", m_name.c_str() ); + for ( unsigned ii=0; ii < n; ii += m_instr_mem[ii]->inst_size() ) { // handle branch instructions + ptx_instruction *pI = m_instr_mem[ii]; + pI->pre_decode(); + } + printf(" done.\n"); + fflush(stdout); + m_assembled = true; } @@ -659,6 +666,10 @@ void ptx_instruction::pre_decode() } } } + + // get reconvergence pc + reconvergence_pc = get_converge_point(pc); + m_decoded=true; } @@ -1609,7 +1620,15 @@ struct rec_pts find_reconvergence_points( function_info *finfo ) return tmp; } -unsigned int get_converge_point( unsigned int pc, void *thd ) +address_type get_return_pc( void *thd ) +{ + // function call return + ptx_thread_info *the_thread = (ptx_thread_info*)thd; + assert( the_thread != NULL ); + return the_thread->get_return_PC(); +} + +address_type get_converge_point( address_type pc ) { // the branch could encode the reconvergence point and/or a bit that indicates the // reconvergence point is the return PC on the call stack in the case the branch has @@ -1624,16 +1643,12 @@ unsigned int get_converge_point( unsigned int pc, void *thd ) for (; i < tmp.s_num_recon; ++i) { if (tmp.s_kernel_recon_points[i].source_pc == pc) { if( tmp.s_kernel_recon_points[i].target_pc == (unsigned) -2 ) { - // function call return - ptx_thread_info *the_thread = (ptx_thread_info*)thd; - assert( the_thread != NULL ); - return the_thread->get_return_PC(); + return RECONVERGE_RETURN_PC; } else { return tmp.s_kernel_recon_points[i].target_pc; } } } - assert(i < tmp.s_num_recon); - abort(); // returning garbage! + return NO_BRANCH_DIVERGENCE; } diff --git a/src/cuda-sim/cuda-sim.h b/src/cuda-sim/cuda-sim.h index 0e97b97..e7c1965 100644 --- a/src/cuda-sim/cuda-sim.h +++ b/src/cuda-sim/cuda-sim.h @@ -47,7 +47,10 @@ const warp_inst_t *ptx_fetch_inst( address_type pc ); const struct gpgpu_ptx_sim_kernel_info* ptx_sim_kernel_info(const class function_info *kernel); void ptx_print_insn( address_type pc, FILE *fp ); void set_param_gpgpu_num_shaders(int num_shaders); -unsigned int get_converge_point(unsigned int pc, void *thd); + +#define RECONVERGE_RETURN_PC ((address_type)-2) +#define NO_BRANCH_DIVERGENCE ((address_type)-1) +address_type get_return_pc( void *thd ); const char *get_ptxinfo_kname(); void print_ptxinfo(); void clear_ptxinfo(); diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc index b98e774..e52fccd 100644 --- a/src/cuda-sim/ptx_ir.cc +++ b/src/cuda-sim/ptx_ir.cc @@ -756,6 +756,8 @@ void function_info::print_idominators() unsigned function_info::get_num_reconvergence_pairs() { if (!num_reconvergence_pairs) { + if( m_basic_blocks.size() == 0 ) + return 0; for (unsigned i=0; i< (m_basic_blocks.size()-1); i++) { //last basic block containing exit obviously won't have a pair if (m_basic_blocks[i]->ptx_end->get_opcode() == BRA_OP) { num_reconvergence_pairs++; @@ -768,6 +770,8 @@ unsigned function_info::get_num_reconvergence_pairs() void function_info::get_reconvergence_pairs(gpgpu_recon_t* recon_points) { unsigned idx=0; //array index + if( m_basic_blocks.size() == 0 ) + return; for (unsigned i=0; i< (m_basic_blocks.size()-1); i++) { //last basic block containing exit obviously won't have a pair #ifdef DEBUG_GET_RECONVERG_PAIRS printf("i=%d\n", i); fflush(stdout); diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 169adbe..7a0ad59 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -149,9 +149,9 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, 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 simt_stack*[config->max_warps_per_shader]; + m_simt_stack = new simt_stack*[config->max_warps_per_shader]; for (unsigned i = 0; i < config->max_warps_per_shader; ++i) - m_pdom_warp[i] = new simt_stack(i,this); + m_simt_stack[i] = new simt_stack(i,this); m_scoreboard = new Scoreboard(m_sid, m_config->max_warps_per_shader); m_operand_collector.add_port( m_config->gpgpu_operand_collector_num_units_sp, @@ -201,7 +201,7 @@ void shader_core_ctx::reinit(unsigned start_thread, unsigned end_thread, bool re } for (unsigned i = start_thread / m_config->warp_size; i < end_thread / m_config->warp_size; ++i) { m_warp[i].reset(); - m_pdom_warp[i]->reset(); + m_simt_stack[i]->reset(); } } @@ -223,7 +223,7 @@ void shader_core_ctx::init_warps( unsigned cta_id, unsigned start_thread, unsign active_threads.set(t); } } - m_pdom_warp[i]->launch(start_pc,active_threads); + m_simt_stack[i]->launch(start_pc,active_threads); m_warp[i].init(start_pc,cta_id,i,active_threads); m_not_completed += n_active; } @@ -241,78 +241,76 @@ address_type shader_core_ctx::next_pc( int tid ) const return the_thread->get_pc(); // PC should already be updatd to next PC at this point (was set in shader_decode() last time thread ran) } -void simt_stack::update() +void simt_stack::update( simt_mask_t &thread_done, addr_vector_t &next_pc, address_type recvg_pc ) { - int wtid = m_warp_size*m_warp_id; - int stack_top = m_stack_top; + int stack_top = m_stack_top; - address_type top_pc = m_pc[stack_top]; - simt_mask_t top_active_mask = m_active_mask[stack_top]; - address_type top_recvg_pc = m_recvg_pc[stack_top]; + assert( next_pc.size() == m_warp_size ); - assert(top_active_mask.any()); + simt_mask_t top_active_mask = m_active_mask[stack_top]; + address_type top_recvg_pc = m_recvg_pc[stack_top]; - const address_type null_pc = 0; - bool warp_diverged = false; - address_type new_recvg_pc = null_pc; - while (top_active_mask.any()) { + assert(top_active_mask.any()); - // extract a group of threads with the same next PC among the active threads in the warp - address_type tmp_next_pc = null_pc; - simt_mask_t tmp_active_mask; - class ptx_thread_info *first_active_thread=NULL; - for (int i = m_warp_size - 1; i >= 0; i--) { - if ( top_active_mask.test(i) ) { // is this thread active? - if (m_shader->ptx_thread_done(wtid+i)) { - top_active_mask.reset(i); // remove completed thread from active mask - } else if (tmp_next_pc == null_pc) { - first_active_thread=m_shader->get_thread_state(wtid+i); - tmp_next_pc = first_active_thread->get_pc(); - tmp_active_mask.set(i); - top_active_mask.reset(i); - } else if (tmp_next_pc == m_shader->get_thread_state(wtid+i)->get_pc()) { - tmp_active_mask.set(i); - top_active_mask.reset(i); - } - } - } + const address_type null_pc = 0; + bool warp_diverged = false; + address_type new_recvg_pc = null_pc; + while (top_active_mask.any()) { - // discard the new entry if its PC matches with reconvergence PC - // that automatically reconverges the entry - if (tmp_next_pc == top_recvg_pc) continue; + // extract a group of threads with the same next PC among the active threads in the warp + address_type tmp_next_pc = null_pc; + simt_mask_t tmp_active_mask; + for (int i = m_warp_size - 1; i >= 0; i--) { + if ( top_active_mask.test(i) ) { // is this thread active? + if (thread_done.test(i)) { + top_active_mask.reset(i); // remove completed thread from active mask + } else if (tmp_next_pc == null_pc) { + tmp_next_pc = next_pc[i]; + tmp_active_mask.set(i); + top_active_mask.reset(i); + } else if (tmp_next_pc == next_pc[i]) { + tmp_active_mask.set(i); + top_active_mask.reset(i); + } + } + } - // this new entry is not converging - // if this entry does not include thread from the warp, divergence occurs - if (top_active_mask.any() && !warp_diverged ) { - warp_diverged = true; - // modify the existing top entry into a reconvergence entry in the pdom stack - new_recvg_pc = get_converge_point(top_pc,first_active_thread); - if (new_recvg_pc != top_recvg_pc) { - m_pc[stack_top] = new_recvg_pc; - m_branch_div_cycle[stack_top] = gpu_sim_cycle; - stack_top += 1; - m_branch_div_cycle[stack_top] = 0; - } - } + // discard the new entry if its PC matches with reconvergence PC + // that automatically reconverges the entry + if (tmp_next_pc == top_recvg_pc) continue; - // discard the new entry if its PC matches with reconvergence PC - if (warp_diverged && tmp_next_pc == new_recvg_pc) continue; + // this new entry is not converging + // if this entry does not include thread from the warp, divergence occurs + if (top_active_mask.any() && !warp_diverged ) { + warp_diverged = true; + // modify the existing top entry into a reconvergence entry in the pdom stack + new_recvg_pc = recvg_pc; + if (new_recvg_pc != top_recvg_pc) { + m_pc[stack_top] = new_recvg_pc; + m_branch_div_cycle[stack_top] = gpu_sim_cycle; + stack_top += 1; + m_branch_div_cycle[stack_top] = 0; + } + } - // update the current top of pdom stack - m_pc[stack_top] = tmp_next_pc; - m_active_mask[stack_top] = tmp_active_mask; - if (warp_diverged) { - m_calldepth[stack_top] = 0; - m_recvg_pc[stack_top] = new_recvg_pc; - } else { - m_recvg_pc[stack_top] = top_recvg_pc; - } - stack_top += 1; // set top to next entry in the pdom stack - } - m_stack_top = stack_top - 1; + // discard the new entry if its PC matches with reconvergence PC + if (warp_diverged && tmp_next_pc == new_recvg_pc) continue; - assert(m_stack_top >= 0); - assert(m_stack_top < m_warp_size * 2); + // update the current top of pdom stack + m_pc[stack_top] = tmp_next_pc; + m_active_mask[stack_top] = tmp_active_mask; + if (warp_diverged) { + m_calldepth[stack_top] = 0; + m_recvg_pc[stack_top] = new_recvg_pc; + } else { + m_recvg_pc[stack_top] = top_recvg_pc; + } + stack_top += 1; // set top to next entry in the pdom stack + } + m_stack_top = stack_top - 1; + + assert(m_stack_top >= 0); + assert(m_stack_top < m_warp_size * 2); } void gpgpu_sim::get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ) @@ -324,7 +322,7 @@ void gpgpu_sim::get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *p void shader_core_ctx::get_pdom_stack_top_info( unsigned tid, unsigned *pc, unsigned *rpc ) const { unsigned warp_id = tid/m_config->warp_size; - m_pdom_warp[warp_id]->get_pdom_stack_top_info(pc,rpc); + m_simt_stack[warp_id]->get_pdom_stack_top_info(pc,rpc); } void simt_stack::get_pdom_stack_top_info( unsigned *pc, unsigned *rpc ) const @@ -613,7 +611,28 @@ void shader_core_ctx::issue_warp( warp_inst_t *&pipe_reg, const warp_inst_t *nex m_barriers.warp_reaches_barrier(m_warp[warp_id].get_cta_id(),warp_id); else if( next_inst->op == MEMORY_BARRIER_OP ) m_warp[warp_id].set_membar(); - m_pdom_warp[warp_id]->update(); + + // extract thread done and next pc information from functional model here + simt_mask_t thread_done; + addr_vector_t next_pc; + + unsigned wtid = warp_id * m_config->warp_size; + for (unsigned i = 0; i < m_config->warp_size; i++) { + if( ptx_thread_done(wtid+i) ) { + thread_done.set(i); + next_pc.push_back( (address_type)-1 ); + } else { + class ptx_thread_info *info = get_thread_state(wtid+i); + assert( info ); + if( pipe_reg->reconvergence_pc == RECONVERGE_RETURN_PC ) + pipe_reg->reconvergence_pc = get_return_pc(info); + next_pc.push_back( info->get_pc() ); + } + } + + // use to update simt stack here + m_simt_stack[warp_id]->update(thread_done,next_pc,pipe_reg->reconvergence_pc); + m_scoreboard->reserveRegisters(pipe_reg); m_warp[warp_id].set_next_pc(next_inst->pc + next_inst->isize); } @@ -632,7 +651,7 @@ void shader_core_ctx::decode() const warp_inst_t *pI = m_warp[warp_id].ibuffer_next_inst(); bool valid = m_warp[warp_id].ibuffer_next_valid(); unsigned pc,rpc; - m_pdom_warp[warp_id]->get_pdom_stack_top_info(&pc,&rpc); + m_simt_stack[warp_id]->get_pdom_stack_top_info(&pc,&rpc); if( pI ) { assert(valid); if( pc != pI->pc ) { @@ -643,7 +662,7 @@ void shader_core_ctx::decode() valid_inst = true; if ( !m_scoreboard->checkCollision(warp_id, pI) ) { ready_inst = true; - const active_mask_t &active_mask = m_pdom_warp[warp_id]->get_active_mask(); + const active_mask_t &active_mask = m_simt_stack[warp_id]->get_active_mask(); assert( m_warp[warp_id].inst_in_pipeline() ); if ( (pI->op == LOAD_OP) || (pI->op == STORE_OP) || (pI->op == MEMORY_BARRIER_OP) ) { if( m_pipeline_reg[ID_OC_MEM]->empty() ) { @@ -1297,7 +1316,7 @@ void shader_core_ctx::display_simt_state(FILE *fout, int mask ) const if ( nactive == 0 ) { continue; } - m_pdom_warp[i]->print(fout); + m_simt_stack[i]->print(fout); } fprintf(fout,"\n"); } diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index c312d62..9200c99 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -282,6 +282,7 @@ inline unsigned wid_from_hw_tid(unsigned tid, unsigned warp_size){return tid/war #define MAX_WARP_SIZE_SIMT_STACK MAX_WARP_SIZE typedef std::bitset<MAX_WARP_SIZE_SIMT_STACK> simt_mask_t; +typedef std::vector<address_type> addr_vector_t; class simt_stack { public: @@ -289,7 +290,7 @@ public: void reset(); void launch( address_type start_pc, const simt_mask_t &active_mask ); - void update(); + void update( simt_mask_t &thread_done, addr_vector_t &next_pc, address_type recvg_pc ); const simt_mask_t &get_active_mask() const; void get_pdom_stack_top_info( unsigned *pc, unsigned *rpc ) const; @@ -1214,10 +1215,10 @@ private: std::vector<shd_warp_t> m_warp; // per warp information array barrier_set_t m_barriers; ifetch_buffer_t m_inst_fetch_buffer; - simt_stack **m_pdom_warp; // pdom reconvergence context for each warp - warp_inst_t** m_pipeline_reg; - Scoreboard *m_scoreboard; - opndcoll_rfu_t m_operand_collector; + simt_stack **m_simt_stack; // pdom based reconvergence context for each warp + warp_inst_t **m_pipeline_reg; + Scoreboard *m_scoreboard; + opndcoll_rfu_t m_operand_collector; // execute unsigned m_num_function_units; |
