summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/warp_tracker.cc
diff options
context:
space:
mode:
authorTor Aamodt <[email protected]>2010-10-01 08:55:28 -0800
committerTor Aamodt <[email protected]>2010-10-01 08:55:28 -0800
commit11b308e7363e937966b035b4891db32b4eece3bf (patch)
tree50ca4c9ad6f163ac4acb2bf505e64dfebed66947 /src/gpgpu-sim/warp_tracker.cc
parentbb820c116764d7a1b8e071137d32b74e7f34dd2f (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.cc471
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
}