diff options
| author | Tor Aamodt <[email protected]> | 2010-10-01 08:55:28 -0800 |
|---|---|---|
| committer | Tor Aamodt <[email protected]> | 2010-10-01 08:55:28 -0800 |
| commit | 11b308e7363e937966b035b4891db32b4eece3bf (patch) | |
| tree | 50ca4c9ad6f163ac4acb2bf505e64dfebed66947 /src/gpgpu-sim/warp_tracker.cc | |
| parent | bb820c116764d7a1b8e071137d32b74e7f34dd2f (diff) | |
integrating recent changes from fermi-test into fermi
(i'll use "fermi" for more disruptive changes to the pipeline model such
as updating the MSHRs and getting rid of the warp tracker, ripping out DWF, etc...)
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7805]
Diffstat (limited to 'src/gpgpu-sim/warp_tracker.cc')
| -rw-r--r-- | src/gpgpu-sim/warp_tracker.cc | 471 |
1 files changed, 47 insertions, 424 deletions
diff --git a/src/gpgpu-sim/warp_tracker.cc b/src/gpgpu-sim/warp_tracker.cc index d701c8f..44cbbc6 100644 --- a/src/gpgpu-sim/warp_tracker.cc +++ b/src/gpgpu-sim/warp_tracker.cc @@ -70,87 +70,22 @@ using namespace std; - -void register_cta_thread_exit(shader_core_ctx_t *shader, int cta_num ); - /* * Constructor for warp_tracker_pool. * * Resizes the warp_tracker map and pool and allocates empty warp_trackers. * * @param tid_in Array of thread id's corresponding to a warp - * @param *shd Pointer to the shader core - * - * @return Pointer to a warp_tracker - */ -warp_tracker_pool::warp_tracker_pool(unsigned gpu_n_shader, unsigned gpu_n_thread_per_shader) { - this->gpu_n_shader = gpu_n_shader; - this->gpu_n_thread_per_shader = gpu_n_thread_per_shader; - - // Resize the warp tracker map - warp_tracker_map.resize(gpu_n_shader); - for(unsigned i=0; i<gpu_n_shader; i++) { - warp_tracker_map[i].resize(gpu_n_thread_per_shader); - } - - // Create a pool of warp_trackers - warp_tracker_list.resize(gpu_n_shader * gpu_n_thread_per_shader); - - // Add all warp_trackers to the list of free warp_trackers - std::list<warp_tracker>::iterator it; - for(it=warp_tracker_list.begin(); it!=warp_tracker_list.end(); it++) - warp_tracker_free_list.push_back(&(*it)); - -} - -/* - * Fetch a free warp_tracker from the pool of warp_trackers. Assigns the warp_tracker to - * the input warp. - * - * If there are no free warp_trackers in the pool, the pool is extended by allocating more - * warp_trackers. - * - * @param tid_in Array of thread id's corresponding to a warp - * @param *shd Pointer to the shader core - * - * @return Pointer to a warp_tracker - */ -warp_tracker* warp_tracker_pool::alloc_warp_tracker( int *tid_in, shader_core_ctx_t *shd, address_type pc ) { - // If no free warp trackers are available, allocate some more - if(warp_tracker_free_list.empty()) { - printf("warp_tracker_list empty (size=%d) - allocating new warp_trackers\n", size()); - fflush(stdout); - // Warp tracker list is empty, resize the list - unsigned previous_size = warp_tracker_list.size(); - warp_tracker_list.resize( previous_size + this->gpu_n_thread_per_shader); - - // Add newly allocated warp trackers to list of free warp trackers - std::list<warp_tracker>::iterator it = warp_tracker_list.begin(); - for(unsigned i=0; i<previous_size; i++) - it++; // Increment iterator - for(; it!=warp_tracker_list.end(); it++) - warp_tracker_free_list.push_back(&(*it)); - } - - assert(!warp_tracker_free_list.empty()); - // Fetch a free warp_tracker - warp_tracker* wpt = warp_tracker_free_list.front(); - warp_tracker_free_list.pop_front(); - wpt->set_warp(tid_in, shd, pc); - - return wpt; -} - -/* - * Free the warp_tracker. - * - * Puts the warp_tracker back into the pool of free warp_trackers. - * - * @param wpt Pointer to a warp_tracker + * @param *my_shader Pointer to the shader core * */ -void warp_tracker_pool::free_warp_tracker(warp_tracker* wpt) { - warp_tracker_free_list.push_back(wpt); +warp_tracker_pool::warp_tracker_pool(class shader_core_ctx *my_shader) +{ + m_shader=my_shader; + const shader_core_config *config = my_shader->get_config(); + gpu_n_thread_per_shader = config->n_thread_per_shader; + warp_size = config->warp_size; + warp_tracker_map.resize(gpu_n_thread_per_shader); } /* @@ -163,24 +98,15 @@ void warp_tracker_pool::free_warp_tracker(warp_tracker* wpt) { * @param *shd Pointer to the shader core * */ -void warp_tracker_pool::wpt_register_warp( int *tid_in, shader_core_ctx_t *shd, address_type pc) +void warp_tracker_pool::wpt_register_warp( int *tid_in, address_type pc, unsigned n_thd, unsigned warp_size ) { - int sid = shd->sid; - unsigned i; - int n_thd = 0; - for (i=0; i<warp_size; i++) { - if (tid_in[i] >= 0) n_thd++; - } - - if (!n_thd) return; - - warp_tracker *wpt = this->alloc_warp_tracker(tid_in, shd, pc); - + assert(n_thd); + warp_tracker *wpt = new warp_tracker(tid_in,pc,warp_size); // assign the new warp_tracker to warp_tracker_map - for (i=0; i<warp_size; i++) { + for (unsigned i=0; i<warp_size; i++) { if (tid_in[i] >= 0) { - assert( map_get_warp_tracker(sid,tid_in[i],pc) == NULL ); - map_set_warp_tracker(sid, tid_in[i], pc, wpt); + assert( map_get_warp_tracker(tid_in[i],pc) == NULL ); + map_set_warp_tracker(tid_in[i], pc, wpt); } } } @@ -193,10 +119,9 @@ void warp_tracker_pool::wpt_register_warp( int *tid_in, shader_core_ctx_t *shd, * * @return Returns true is all threads in the warp have completed. */ -int warp_tracker_pool::wpt_signal_avail( int tid, shader_core_ctx_t *shd, address_type pc ) +int warp_tracker_pool::wpt_signal_avail( int tid, address_type pc ) { - int sid = shd->sid; - warp_tracker *wpt = map_get_warp_tracker(sid,tid,pc); + warp_tracker *wpt = map_get_warp_tracker(tid,pc); assert(wpt != NULL); @@ -215,22 +140,13 @@ int warp_tracker_pool::wpt_signal_avail( int tid, shader_core_ctx_t *shd, addres * by number of active threads. * * @param tid Thread that is exiting - * @param *shd Pointer to the shader core * */ -void warp_tracker_pool::wpt_deregister_warp( int tid, shader_core_ctx_t *shd, address_type pc ) { - int sid = shd->sid; - warp_tracker *wpt = map_get_warp_tracker(sid,tid,pc); +void warp_tracker_pool::wpt_deregister_warp( int tid, address_type pc ) { + warp_tracker *wpt = map_get_warp_tracker(tid,pc); assert(wpt != NULL); - - // the warp is ready to be fetched again, remove this warp_tracker - for (unsigned i=0; i<warp_size; i++) { - if (wpt->tid[i] >= 0) { - map_clear_warp_tracker(sid,wpt->tid[i],pc); - } - } - - free_warp_tracker( wpt ); + map_clear_warp_tracker(wpt); + delete wpt; } @@ -241,30 +157,26 @@ void warp_tracker_pool::wpt_deregister_warp( int tid, shader_core_ctx_t *shd, ad * threads and removed the warp from warp tracker. * * @param tid Thread that is exiting - * @param *shd Pointer to the shader core * * @return The warp's mask of active threads. */ -int warp_tracker_pool::wpt_signal_complete( int tid, shader_core_ctx_t *shd, address_type pc ) +int warp_tracker_pool::wpt_signal_complete( int tid, address_type pc ) { - int sid = shd->sid; - warp_tracker *wpt = map_get_warp_tracker(sid,tid,pc); + warp_tracker *wpt = map_get_warp_tracker(tid,pc); assert(wpt != NULL); // signal the warp tracker if (wpt->complete_thd(tid)) { // if the warp has completed execution, remove this warp_tracker + map_clear_warp_tracker(wpt); int warp_mask = 0; for (unsigned i=0; i<warp_size; i++) { - if (wpt->tid[i] >= 0) { - register_cta_thread_exit(shd, wpt->tid[i] ); - map_clear_warp_tracker(sid,wpt->tid[i],pc); + if (wpt->tid(i) >= 0) { + m_shader->register_cta_thread_exit( wpt->tid(i) ); warp_mask |= (1 << i); } } - - free_warp_tracker( wpt ); - + delete wpt; return warp_mask; } else { return 0; @@ -276,373 +188,84 @@ int warp_tracker_pool::wpt_signal_complete( int tid, shader_core_ctx_t *shd, add * * Checks if any pc of the given tid maps to a warp_tracker * - * @param *shd Pointer to the shader core * @param tid Thread to check * * @return True is thread is being tracked */ -bool warp_tracker_pool::wpt_thread_in_wpt(shader_core_ctx *shd, int tid) { - int sid = shd->sid; +bool warp_tracker_pool::wpt_thread_in_wpt(int tid) { std::map<address_type, warp_tracker*>::iterator it; - for(it=warp_tracker_map[sid][tid].begin(); it!=warp_tracker_map[sid][tid].end(); it++) + for(it=warp_tracker_map[tid].begin(); it!=warp_tracker_map[tid].end(); it++) if((*it).second != NULL) return true; return false; } - - -warp_tracker_pool& get_warp_tracker_pool(){ - static warp_tracker_pool* wpt_pool = new warp_tracker_pool(gpu_n_shader, gpu_n_thread_per_shader); - return *wpt_pool; -} - - -//------------------------------------------------------------------------------- - -/* - -static warp_tracker ***warp_tracker_map; -static unsigned **g_warp_tracker_map_setl_cycle; -static warp_tracker *warp_tracker_pool = NULL; -static list<warp_tracker*> free_wpt; - -warp_tracker* alloc_warp_tracker( int *tid_in, shader_core_ctx_t *shd ) -{ - assert(!free_wpt.empty()); - warp_tracker* wpt = free_wpt.front(); - free_wpt.pop_front(); - - wpt->set_warp(tid_in, shd); - - return wpt; -} - -void free_warp_tracker(warp_tracker* wpt) -{ - free_wpt.push_back(wpt); -} - -void init_warp_tracker( ) -{ - unsigned int i; - - warp_tracker_map = (warp_tracker ***)calloc(gpu_n_shader, sizeof(warp_tracker **)); - g_warp_tracker_map_setl_cycle = (unsigned**)calloc(gpu_n_shader, sizeof(unsigned*)); - for (i=0; i<gpu_n_shader; i++) { - warp_tracker_map[i] = (warp_tracker **)calloc(gpu_n_thread_per_shader, sizeof(warp_tracker *)); - g_warp_tracker_map_setl_cycle[i] = (unsigned*)calloc(gpu_n_thread_per_shader, sizeof(unsigned)); - } - - // max possible number of warps is just when each thread has its own warp - warp_tracker_pool = new warp_tracker[gpu_n_shader * gpu_n_thread_per_shader]; - printf("%d %d %d %d\n", warp_size, gpu_n_shader, gpu_n_thread_per_shader, - warp_size * gpu_n_shader * gpu_n_thread_per_shader); - for (i=0; i<gpu_n_shader*gpu_n_thread_per_shader; i++) { - free_wpt.push_back(&(warp_tracker_pool[i])); - } - printf("%zd\n", free_wpt.size()); -} - -void wpt_register_warp( int *tid_in, shader_core_ctx_t *shd ) -{ - int sid = shd->sid; - unsigned i; - int n_thd = 0; - for (i=0; i<warp_size; i++) { - if (tid_in[i] >= 0) n_thd++; - } - - if (!n_thd) return; - - warp_tracker *wpt = alloc_warp_tracker(tid_in, shd); - - // assign the new warp_tracker to warp_tracker_map - for (i=0; i<warp_size; i++) { - if (tid_in[i] >= 0) { - assert( warp_tracker_map[sid][tid_in[i]] == NULL ); - warp_tracker_map[sid][tid_in[i]] = wpt; - g_warp_tracker_map_setl_cycle[sid][tid_in[i]] = gpu_tot_sim_cycle + gpu_sim_cycle; - } - } -} - -int wpt_signal_avail( int tid, shader_core_ctx_t *shd ) -{ - int sid = shd->sid; - warp_tracker *wpt = warp_tracker_map[sid][tid]; - assert(wpt != NULL); - - - // signal the warp tracker - if (wpt->avail_thd()) { - return 1; - } else { - return 0; - } -} - -// Unlock a warp -void wpt_unlock_threads( int tid, shader_core_ctx_t *shd ) { - int sid = shd->sid; - warp_tracker *wpt = warp_tracker_map[sid][tid]; - assert(wpt != NULL); - - int thd_unlocked = 0; - // Unlock - for (unsigned i=0; i<warp_size; i++) { - if (wpt->tid[i] >= 0) { - shd->thread[wpt->tid[i]].avail4fetch++; - assert(shd->thread[wpt->tid[i]].avail4fetch <= 1); - assert( shd->warp[wpt->tid[i]/warp_size].n_avail4fetch < warp_size ); - shd->warp[wpt->tid[i]/warp_size].n_avail4fetch++; - thd_unlocked = 1; - } - } - - if (shd->model == POST_DOMINATOR || shd->model == NO_RECONVERGE) { - // Do nothing - } else { - // For this case, submit to commit_queue - if (shd->using_commit_queue && thd_unlocked) { - int *tid_unlocked = alloc_commit_warp(); - memcpy(tid_unlocked, wpt->tid, sizeof(int)*warp_size); - dq_push(shd->thd_commit_queue,(void*)tid_unlocked); - } - } - - // the warp is ready to be fetched again, remove this warp_tracker - for (unsigned i=0; i<warp_size; i++) { - if (wpt->tid[i] >= 0) { - warp_tracker_map[sid][wpt->tid[i]] = NULL; - g_warp_tracker_map_setl_cycle[sid][wpt->tid[i]] = gpu_tot_sim_cycle + gpu_sim_cycle; - } - } - - free_warp_tracker( wpt ); -} - -*/ - -/* - * Signal that the a thread is done and is exiting (exit instruction) - * - * Marks a thread as completed. If all threads in the warp have completed, call register_cta_thread_exit on all - * threads and removed the warp from warp tracker. - * - * @param tid Thread that is exiting - * @param *shd Pointer to the shader core - * - * @return The warp's mask of active threads. - */ -// - -/* -int wpt_signal_complete( int tid, shader_core_ctx_t *shd ) -{ - int sid = shd->sid; - warp_tracker *wpt = warp_tracker_map[sid][tid]; - assert(wpt != NULL); - - // signal the warp tracker - if (wpt->complete_thd(tid)) { - // if the warp has completed execution, remove this warp_tracker - int warp_mask = 0; - for (unsigned i=0; i<warp_size; i++) { - if (wpt->tid[i] >= 0) { - register_cta_thread_exit(shd, wpt->tid[i] ); - warp_tracker_map[sid][wpt->tid[i]] = NULL; - g_warp_tracker_map_setl_cycle[sid][wpt->tid[i]] = gpu_tot_sim_cycle + gpu_sim_cycle; - warp_mask |= (1 << i); - } - } - - free_warp_tracker( wpt ); - - return warp_mask; - } else { - return 0; - } -} -*/ - //------------------------------------------------------------------------------------ -class thread_pc_tracker_class { -public: - address_type *thd_pc; // tracks the pc of each thread - map<address_type, unsigned> pc_count; - unsigned acc_pc_count; - int simd_width; - static map<unsigned, unsigned> histogram; - - thread_pc_tracker_class( ) { - this->acc_pc_count = 0; - this->simd_width = 0; - this->thd_pc = NULL; - } - - thread_pc_tracker_class(int simd_width, int thread_count) { - this->acc_pc_count = 0; - this->simd_width = simd_width; - this->thd_pc = new address_type[thread_count]; - memset( this->thd_pc, 0, sizeof(address_type)*thread_count); - } - - void add_threads( int *tid, address_type pc ) { - for (int i=0; i<simd_width; i++) { - if (tid[i] != -1) { - pc_count[pc] += 1; // automatically create a new entry if not exist - thd_pc[tid[i]] = pc; - } - } - } - - void sub_threads( int *tid ) { - for (int i=0; i<simd_width; i++) { - if (tid[i] != -1) { - address_type pc = thd_pc[tid[i]]; - if (pc == 0) break; - pc_count[pc] -= 1; - assert((int)pc_count[pc] >= 0); - if (pc_count[pc] == 0) pc_count.erase(pc); // manually erasing entries with 0 count - } - } - } - - void update_acc_count( ) { - acc_pc_count += pc_count.size(); - histogram[pc_count.size()] += 1; - } - - void set_threads_pc ( int *tid, address_type pc ) { - sub_threads(tid); - add_threads(tid, pc); - update_acc_count( ); - } - - unsigned get_acc_pc_count( ) { return acc_pc_count;} - - unsigned count( ) { return pc_count.size();} - - static void histo_print( FILE* fout ) { - if (histogram.empty()) return; // do not output anything if the histogram is empty - map<unsigned, unsigned>::iterator i; - fprintf(fout, "Thread PC Histogram: "); - for (i = histogram.begin(); i != histogram.end(); i++) { - fprintf(fout, "%d:%d ", i->first, i->second); - } - fprintf(fout, "\n"); - } -}; - -map<unsigned, unsigned> thread_pc_tracker_class::histogram; +map<unsigned, unsigned> thread_pc_tracker::histogram; -thread_pc_tracker_class *thread_pc_tracker = NULL; +thread_pc_tracker *thread_pc_tracker = NULL; void print_thread_pc_histogram( FILE *fout ) { - thread_pc_tracker_class::histo_print(fout); + thread_pc_tracker::histo_print(fout); } -void print_thread_pc( FILE *fout ) +void print_thread_pc( FILE *fout, unsigned n_shader ) { fprintf(fout, "SHD_PC_C: "); - for (unsigned i=0; i<gpu_n_shader; i++) { + for (unsigned i=0; i<n_shader; i++) { fprintf(fout, "%d ", thread_pc_tracker[i].get_acc_pc_count() ); } fprintf(fout, "\n"); } -void track_thread_pc( int shader_id, int *tid, address_type pc ) -{ - if (!thread_pc_tracker) { - thread_pc_tracker = new thread_pc_tracker_class[gpu_n_shader]; - for (unsigned i=0; i<gpu_n_shader; i++) { - thread_pc_tracker[i] = thread_pc_tracker_class(warp_size, gpu_n_thread_per_shader); - } - } - thread_pc_tracker[shader_id].set_threads_pc( tid, pc ); -} - -//------------------------------------------------------------------------------------ - -static int *commit_warp_pool = NULL; -static queue<int*> free_commit_warp_q; - -void init_commit_warp( ) -{ - unsigned int num_warp = warp_size * gpu_n_shader * gpu_n_thread_per_shader; - commit_warp_pool = new int[num_warp]; - for (unsigned int i=0; i<num_warp; i+=warp_size) { - free_commit_warp_q.push(&(commit_warp_pool[i])); - } -} - -int* alloc_commit_warp( ) -{ - if (!commit_warp_pool) { - init_commit_warp( ); - } - - assert(!free_commit_warp_q.empty()); - int *new_commit_warp = free_commit_warp_q.front(); - free_commit_warp_q.pop(); - - return new_commit_warp; -} - -void free_commit_warp( int *commit_warp ) -{ - free_commit_warp_q.push(commit_warp); -} - // uncomment to enable checking for warp consistency // #define CHECK_WARP_CONSISTENCY -void check_stage_pcs( shader_core_ctx_t *shader, unsigned stage ) +void shader_core_ctx::check_stage_pcs( unsigned stage ) { #ifdef CHECK_WARP_CONSISTENCY address_type inst_pc = (address_type)-1; unsigned tid; - if( shader->model == MIMD ) + if( m_config->model == MIMD ) return; std::set<unsigned> tids; - for ( int i = 0; i < pipe_simd_width; i++) { - if (shader->pipeline_reg[i][stage].hw_thread_id == -1 ) + for ( int i = 0; i < m_config->warp_size; i++) { + if (m_pipeline_reg[i][stage].hw_thread_id == -1 ) continue; if ( inst_pc == (address_type)-1 ) - inst_pc = shader->pipeline_reg[i][stage].pc; - tid = shader->pipeline_reg[i][stage].hw_thread_id; + inst_pc = m_pipeline_reg[i][stage].pc; + tid = m_pipeline_reg[i][stage].hw_thread_id; assert( tids.find(tid) == tids.end() ); tids.insert(tid); - assert( inst_pc == shader->pipeline_reg[i][stage].pc ); + assert( inst_pc == m_pipeline_reg[i][stage].pc ); } #endif } -void check_pm_stage_pcs( shader_core_ctx_t *shader, unsigned stage ) +void shader_core_ctx::check_pm_stage_pcs( unsigned stage ) { #ifdef CHECK_WARP_CONSISTENCY address_type inst_pc = (address_type)-1; unsigned tid; - if( shader->model == MIMD ) + if( m_config->model == MIMD ) return; std::set<unsigned> tids; - for (int i = 0; i < pipe_simd_width; i++) { - if (shader->pre_mem_pipeline[i][stage].hw_thread_id == -1 ) + for (int i = 0; i < m_config->warp_size; i++) { + if (pre_mem_pipeline[i][stage].hw_thread_id == -1 ) continue; if ( inst_pc == (address_type)-1 ) - inst_pc = shader->pre_mem_pipeline[i][stage].pc; - tid = shader->pre_mem_pipeline[i][stage].hw_thread_id; + inst_pc = pre_mem_pipeline[i][stage].pc; + tid = pre_mem_pipeline[i][stage].hw_thread_id; assert( tids.find(tid) == tids.end() ); tids.insert(tid); - assert( inst_pc == shader->pre_mem_pipeline[i][stage].pc ); + assert( inst_pc == pre_mem_pipeline[i][stage].pc ); } #endif } |
