summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Aamodt <[email protected]>2010-11-30 02:15:16 -0800
committerTor Aamodt <[email protected]>2010-11-30 02:15:16 -0800
commit52a638e84693fff528defbcbd24ecb58216baaba (patch)
tree34449df36f63267119cd048508810a101618fd39
parent7a47f9cd62902d960a989a920d882f3b77fe7b2a (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.h3
-rw-r--r--src/cuda-sim/cuda-sim.cc37
-rw-r--r--src/cuda-sim/cuda-sim.h5
-rw-r--r--src/cuda-sim/ptx_ir.cc4
-rw-r--r--src/gpgpu-sim/shader.cc161
-rw-r--r--src/gpgpu-sim/shader.h11
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;