summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpgpu-sim')
-rw-r--r--src/gpgpu-sim/gpu-sim.cc238
-rw-r--r--src/gpgpu-sim/gpu-sim.h39
-rw-r--r--src/gpgpu-sim/shader.cc104
-rw-r--r--src/gpgpu-sim/shader.h21
-rw-r--r--src/gpgpu-sim/stat-tool.cc23
-rw-r--r--src/gpgpu-sim/stat-tool.h17
6 files changed, 265 insertions, 177 deletions
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index 9bb6a23..9ae05d8 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -276,6 +276,8 @@ void gpgpu_sim_config::reg_options(option_parser_t opp)
option_parser_register(opp, "-gpgpu_clock_domains", OPT_CSTR, &gpgpu_clock_domains,
"Clock Domain Frequencies in MhZ {<Core Clock>:<ICNT Clock>:<L2 Clock>:<DRAM Clock>}",
"500.0:2000.0:2000.0:2000.0");
+ option_parser_register(opp, "-gpgpu_max_concurrent_kernel", OPT_INT32, &max_concurrent_kernel,
+ "maximum kernels that can run concurrently on GPU", "8" );
option_parser_register(opp, "-gpgpu_cflog_interval", OPT_INT32, &gpgpu_cflog_interval,
"Interval between each snapshot in control flow logger",
"0");
@@ -307,7 +309,6 @@ void increment_x_then_y_then_z( dim3 &i, const dim3 &bound)
}
}
-
void gpgpu_sim::launch( kernel_info_t &kinfo )
{
unsigned cta_size = kinfo.threads_per_cta();
@@ -319,15 +320,57 @@ void gpgpu_sim::launch( kernel_info_t &kinfo )
printf(" modify the CUDA source to decrease the kernel block size.\n");
abort();
}
+ unsigned n=0;
+ for(n=0; n < m_running_kernels.size(); n++ ) {
+ if( m_running_kernels[n].done() ) {
+ m_running_kernels[n] = kinfo;
+ break;
+ }
+ }
+ assert(n < m_running_kernels.size());
+}
+
+bool gpgpu_sim::can_start_kernel()
+{
+ for(unsigned n=0; n < m_running_kernels.size(); n++ ) {
+ if( m_running_kernels[n].done() )
+ return true;
+ }
+ return false;
+}
- m_running_kernels.push_back(kinfo);
+bool gpgpu_sim::get_more_cta_left() const
+{
+ if (m_config.gpu_max_cta_opt != 0) {
+ if( m_total_cta_launched >= m_config.gpu_max_cta_opt )
+ return false;
+ }
+ for(unsigned n=0; n < m_running_kernels.size(); n++ ) {
+ if( m_running_kernels[n].valid() && !m_running_kernels[n].no_more_ctas_to_run() )
+ return true;
+ }
+ return false;
+}
+
+kernel_info_t *gpgpu_sim::select_kernel()
+{
+ for(unsigned n=0; n < m_running_kernels.size(); n++ ) {
+ unsigned idx = (n+m_last_issued_kernel+1)%m_config.max_concurrent_kernel;
+ if( m_running_kernels[idx].valid() && !m_running_kernels[idx].no_more_ctas_to_run() ) {
+ m_last_issued_kernel=idx;
+ return &m_running_kernels[idx];
+ }
+ }
+ return NULL;
}
-kernel_info_t *gpgpu_sim::next_grid()
+unsigned gpgpu_sim::finished_kernel()
{
- m_the_kernel = m_running_kernels.front();
- m_running_kernels.pop_front();
- return &m_the_kernel;
+ if( m_finished_kernel.empty() )
+ return 0;
+ unsigned result = m_finished_kernel.front();
+ m_finished_kernel.pop_front();
+ return result;
}
void set_ptx_warp_size(const struct core_config * warp_size);
@@ -360,6 +403,10 @@ gpgpu_sim::gpgpu_sim( const gpgpu_sim_config &config )
time_vector_create(NUM_MEM_REQ_STAT);
fprintf(stdout, "GPGPU-Sim uArch: performance model initialization complete.\n");
+
+ m_running_kernels.resize( config.max_concurrent_kernel );
+ m_last_issued_kernel = 0;
+ m_last_cluster_issue = 0;
}
int gpgpu_sim::shared_mem_size() const
@@ -421,94 +468,76 @@ void gpgpu_sim::reinit_clock_domains(void)
l2_time = 0;
}
-// return the number of cycle required to run all the trace on the gpu
-unsigned int gpgpu_sim::run_gpu_sim()
+bool gpgpu_sim::active()
{
- // run a CUDA grid on the GPU microarchitecture simulator
- kernel_info_t &entry = m_the_kernel;
- size_t program_size = get_kernel_code_size(entry.entry());
-
- int not_completed;
- int mem_busy;
- int icnt2mem_busy;
-
- gpu_sim_cycle = 0;
- not_completed = 1;
- mem_busy = 1;
- icnt2mem_busy = 1;
- more_thread = true;
- g_total_cta_left=0;
- gpu_sim_insn = 0;
- m_shader_stats->new_grid();
+ if (m_config.gpu_max_cycle_opt && (gpu_tot_sim_cycle + gpu_sim_cycle) >= m_config.gpu_max_cycle_opt)
+ return false;
+ if (m_config.gpu_max_insn_opt && (gpu_tot_sim_insn + gpu_sim_insn) >= m_config.gpu_max_insn_opt)
+ return false;
+ if (m_config.gpu_max_cta_opt && (gpu_tot_issued_cta >= m_config.gpu_max_cta_opt) )
+ return false;
+ if (m_config.gpu_deadlock_detect && gpu_deadlock)
+ return false;
+ for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++)
+ if( m_cluster[i]->get_not_completed()>0 )
+ return true;;
+ for (unsigned i=0;i<m_memory_config->m_n_mem;i++)
+ if( m_memory_partition_unit[i]->busy()>0 )
+ return true;;
+ if( icnt_busy() )
+ return true;
+ if( get_more_cta_left() )
+ return true;
+ return false;
+}
- reinit_clock_domains();
- set_param_gpgpu_num_shaders(m_config.num_shader());
- for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++)
- m_cluster[i]->reinit();
- if (m_config.gpu_max_cta_opt != 0) {
- g_total_cta_left = m_config.gpu_max_cta_opt;
- } else {
- g_total_cta_left = m_the_kernel.num_blocks();
- }
- if (m_config.gpu_max_cta_opt != 0) {
- // the maximum number of CTA has been reached, stop any further simulation
- if (gpu_tot_issued_cta >= m_config.gpu_max_cta_opt)
- return 0;
- }
+void gpgpu_sim::init()
+{
+ // run a CUDA grid on the GPU microarchitecture simulator
+ gpu_sim_cycle = 0;
+ gpu_sim_insn = 0;
+ m_total_cta_launched=0;
- if (m_config.gpu_max_cycle_opt && (gpu_tot_sim_cycle + gpu_sim_cycle) >= m_config.gpu_max_cycle_opt) {
- return gpu_sim_cycle;
- }
- if (m_config.gpu_max_insn_opt && (gpu_tot_sim_insn + gpu_sim_insn) >= m_config.gpu_max_insn_opt) {
- return gpu_sim_cycle;
- }
+ reinit_clock_domains();
+ set_param_gpgpu_num_shaders(m_config.num_shader());
+ for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++)
+ m_cluster[i]->reinit();
+ m_shader_stats->new_grid();
+ // initialize the control-flow, memory access, memory latency logger
+ create_thread_CFlogger( m_config.num_shader(), m_shader_config->n_thread_per_shader, 0, m_config.gpgpu_cflog_interval );
+ shader_CTA_count_create( m_config.num_shader(), m_config.gpgpu_cflog_interval);
+ if (m_config.gpgpu_cflog_interval != 0) {
+ insn_warp_occ_create( m_config.num_shader(), m_shader_config->warp_size );
+ shader_warp_occ_create( m_config.num_shader(), m_shader_config->warp_size, m_config.gpgpu_cflog_interval);
+ shader_mem_acc_create( m_config.num_shader(), m_memory_config->m_n_mem, 4, m_config.gpgpu_cflog_interval);
+ shader_mem_lat_create( m_config.num_shader(), m_config.gpgpu_cflog_interval);
+ shader_cache_access_create( m_config.num_shader(), 3, m_config.gpgpu_cflog_interval);
+ set_spill_interval (m_config.gpgpu_cflog_interval * 40);
+ }
- // initialize the control-flow, memory access, memory latency logger
- create_thread_CFlogger( m_config.num_shader(), m_shader_config->n_thread_per_shader, program_size, 0, m_config.gpgpu_cflog_interval );
- shader_CTA_count_create( m_config.num_shader(), m_config.gpgpu_cflog_interval);
- if (m_config.gpgpu_cflog_interval != 0) {
- insn_warp_occ_create( m_config.num_shader(), m_shader_config->warp_size, program_size );
- shader_warp_occ_create( m_config.num_shader(), m_shader_config->warp_size, m_config.gpgpu_cflog_interval);
- shader_mem_acc_create( m_config.num_shader(), m_memory_config->m_n_mem, 4, m_config.gpgpu_cflog_interval);
- shader_mem_lat_create( m_config.num_shader(), m_config.gpgpu_cflog_interval);
- shader_cache_access_create( m_config.num_shader(), 3, m_config.gpgpu_cflog_interval);
- set_spill_interval (m_config.gpgpu_cflog_interval * 40);
- }
+ if (g_network_mode)
+ icnt_init_grid();
+}
- if (g_network_mode)
- icnt_init_grid();
+void gpgpu_sim::print_stats()
+{
+ m_memory_stats->memlatstat_lat_pw();
+ gpu_tot_sim_cycle += gpu_sim_cycle;
+ gpu_tot_sim_insn += gpu_sim_insn;
- last_gpu_sim_insn = 0;
- while (not_completed || mem_busy || icnt2mem_busy) {
- cycle();
- not_completed = 0;
- for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++)
- not_completed += m_cluster[i]->get_not_completed();
- mem_busy = 0;
- for (unsigned i=0;i<m_memory_config->m_n_mem;i++)
- mem_busy += m_memory_partition_unit[i]->busy();
- icnt2mem_busy = icnt_busy();
- if (m_config.gpu_max_cycle_opt && (gpu_tot_sim_cycle + gpu_sim_cycle) >= m_config.gpu_max_cycle_opt)
- break;
- if (m_config.gpu_max_insn_opt && (gpu_tot_sim_insn + gpu_sim_insn) >= m_config.gpu_max_insn_opt)
- break;
- if (m_config.gpu_deadlock_detect && gpu_deadlock)
- break;
- }
- m_memory_stats->memlatstat_lat_pw();
- gpu_tot_sim_cycle += gpu_sim_cycle;
- gpu_tot_sim_insn += gpu_sim_insn;
-
- ptx_file_line_stats_write_file();
+ ptx_file_line_stats_write_file();
+ gpu_print_stat();
- gpu_print_stat();
- if (g_network_mode) {
- interconnect_stats();
- printf("----------------------------Interconnect-DETAILS---------------------------------" );
- icnt_overal_stat();
- printf("----------------------------END-of-Interconnect-DETAILS-------------------------" );
- }
+ if (g_network_mode) {
+ interconnect_stats();
+ printf("----------------------------Interconnect-DETAILS---------------------------------" );
+ icnt_overal_stat();
+ printf("----------------------------END-of-Interconnect-DETAILS-------------------------" );
+ }
+}
+void gpgpu_sim::deadlock_check()
+{
if (m_config.gpu_deadlock_detect && gpu_deadlock) {
fflush(stdout);
printf("\n\nGPGPU-Sim uArch: ERROR ** deadlock detected: last writeback core %u @ gpu_sim_cycle %u (+ gpu_tot_sim_cycle %u) (%u cycles ago)\n",
@@ -545,7 +574,6 @@ unsigned int gpgpu_sim::run_gpu_sim()
fflush(stdout);
abort();
}
- return gpu_sim_cycle;
}
void gpgpu_sim::gpu_print_stat() const
@@ -634,11 +662,11 @@ void shader_core_ctx::mem_instruction_stats(const warp_inst_t &inst)
void shader_core_ctx::issue_block2core( kernel_info_t &kernel )
{
+ set_max_cta(kernel);
+
// find a free CTA context
unsigned free_cta_hw_id=(unsigned)-1;
- unsigned max_concurrent_cta_this_kernel = m_config->max_cta(kernel);
- assert( max_concurrent_cta_this_kernel <= MAX_CTA_PER_SHADER );
- for (unsigned i=0;i<max_concurrent_cta_this_kernel;i++ ) {
+ for (unsigned i=0;i<kernel_max_cta_per_shader;i++ ) {
if( m_cta_status[i]==0 ) {
free_cta_hw_id=i;
break;
@@ -722,6 +750,18 @@ int gpgpu_sim::next_clock_domain(void)
return mask;
}
+void gpgpu_sim::issue_block2core()
+{
+ for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) {
+ unsigned idx = (i+m_last_cluster_issue+1) % m_shader_config->n_simt_clusters;
+ unsigned num = m_cluster[idx]->issue_block2core();
+ if( num ) {
+ m_last_cluster_issue=idx;
+ m_total_cta_launched += num;
+ }
+ }
+}
+
unsigned long long g_single_step=0; // set this in gdb to single step the pipeline
void gpgpu_sim::cycle()
@@ -778,10 +818,11 @@ void gpgpu_sim::cycle()
icnt_transfer();
}
+ last_gpu_sim_insn = 0;
if (clock_mask & CORE) {
// L1 cache + shader core pipeline stages
for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) {
- if (m_cluster[i]->get_not_completed() || more_thread) {
+ if (m_cluster[i]->get_not_completed() || get_more_cta_left() ) {
m_cluster[i]->core_cycle();
}
}
@@ -791,18 +832,9 @@ void gpgpu_sim::cycle()
gpu_sim_cycle++;
if( g_interactive_debugger_enabled )
gpgpu_debug();
-
- for (unsigned i=0;i<m_shader_config->n_simt_clusters && more_thread;i++) {
- if ( ( (m_cluster[i]->get_n_active_cta()+1) <= m_cluster[i]->max_cta(m_the_kernel) ) && g_total_cta_left ) {
- unsigned num = m_cluster[i]->issue_block2core( m_the_kernel );
- if (num >= g_total_cta_left) {
- g_total_cta_left = 0;
- more_thread = false;
- } else
- g_total_cta_left -= num;
- }
- }
-
+
+ issue_block2core();
+
// Flush the caches once all of threads are completed.
if (m_config.gpgpu_flush_cache) {
int all_threads_complete = 1 ;
diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h
index db0b18f..5631ab9 100644
--- a/src/gpgpu-sim/gpu-sim.h
+++ b/src/gpgpu-sim/gpu-sim.h
@@ -192,20 +192,8 @@ public:
m_valid=true;
}
- void set_max_cta( const kernel_info_t &kernel )
- {
- // calcaulte the max cta count and cta size for local memory address mapping
- m_shader_config.gpu_max_cta_per_shader = m_shader_config.max_cta(kernel);
- //gpu_max_cta_per_shader is limited by number of CTAs if not enough
- if( kernel.num_blocks() < m_shader_config.gpu_max_cta_per_shader*num_shader() ) {
- m_shader_config.gpu_max_cta_per_shader = (kernel.num_blocks() / num_shader());
- if (kernel.num_blocks() % num_shader())
- m_shader_config.gpu_max_cta_per_shader++;
- }
- unsigned int gpu_cta_size = kernel.threads_per_cta();
- m_shader_config.gpu_padded_cta_size = (gpu_cta_size%32) ? 32*((gpu_cta_size/32)+1) : gpu_cta_size;
- }
unsigned num_shader() const { return m_shader_config.num_shader(); }
+ unsigned get_max_concurrent_kernel() const { return max_concurrent_kernel; }
private:
void init_clock_domains(void );
@@ -234,6 +222,7 @@ private:
int gpgpu_dram_sched_queue_size;
int gpgpu_cflog_interval;
char * gpgpu_clock_domains;
+ unsigned max_concurrent_kernel;
// visualizer
bool g_visualizer_enabled;
@@ -254,12 +243,17 @@ public:
void set_prop( struct cudaDeviceProp *prop );
void launch( kernel_info_t &kinfo );
- kernel_info_t *next_grid();
+ bool can_start_kernel();
+ unsigned finished_kernel();
+ void set_kernel_done( unsigned uid ) { m_finished_kernel.push_back(uid); }
- unsigned run_gpu_sim();
+ void init();
+ void cycle();
+ bool active();
+ void print_stats();
+ void deadlock_check();
void get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc );
- const kernel_info_t &the_kernel() const { return m_the_kernel; }
int shared_mem_size() const;
int num_registers_per_core() const;
@@ -269,6 +263,8 @@ public:
enum divergence_support_t simd_model() const;
unsigned threads_per_core() const;
+ bool get_more_cta_left() const;
+ kernel_info_t *select_kernel();
const gpgpu_sim_config &get_config() const { return m_config; }
void gpu_print_stat() const;
@@ -278,8 +274,8 @@ private:
// clocks
void reinit_clock_domains(void);
int next_clock_domain(void);
+ void issue_block2core();
- void cycle();
void L2c_print_cache_stat() const;
void shader_print_runtime_stat( FILE *fout );
void shader_print_l1_miss_stat( FILE *fout );
@@ -293,11 +289,12 @@ private:
class simt_core_cluster **m_cluster;
class memory_partition_unit **m_memory_partition_unit;
- kernel_info_t m_the_kernel;
- std::list<kernel_info_t> m_running_kernels;
+ std::vector<kernel_info_t> m_running_kernels;
+ unsigned m_last_issued_kernel;
- unsigned g_total_cta_left;
- bool more_thread;
+ std::list<unsigned> m_finished_kernel;
+ unsigned m_total_cta_launched;
+ unsigned m_last_cluster_issue;
// time of next rising edge
double core_time;
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 7a0ad59..07aeb6d 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -110,6 +110,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
shader_core_stats *stats )
: m_barriers( config->max_warps_per_shader, config->max_cta_per_core )
{
+ m_kernel = NULL;
m_gpu = gpu;
m_cluster = cluster;
m_config = config;
@@ -519,7 +520,8 @@ void shader_core_ctx::fetch()
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);
+ unsigned cta_id = m_warp[warp_id].get_cta_id();
+ register_cta_thread_exit(cta_id);
m_not_completed -= 1;
m_active_threads.reset(tid);
m_thread[tid].m_functional_model_thread_state=NULL;
@@ -725,26 +727,37 @@ address_type shader_core_ctx::translate_local_memaddr( address_type localaddr, u
{
// During functional execution, each thread sees its own memory space for local memory, but these
// need to be mapped to a shared address space for timing simulation. We do that mapping here.
- localaddr /=4;
+
+ address_type thread_base = 0;
+ unsigned max_concurrent_threads=0;
if (m_config->gpgpu_local_mem_map) {
- // Dnew = D*nTpC*nCpS*nS + nTpC*C + T%nTpC
- // C = S + nS*(T/nTpC)
- // D = data index; T = thread; C = CTA; S = shader core; p = per
- // keep threads in a warp contiguous
+ // Dnew = D*N + T%nTpC + nTpC*C
+ // N = nTpC*nCpS*nS (max concurent threads)
+ // C = nS*K + S (hw cta number per gpu)
+ // K = T/nTpC (hw cta number per core)
+ // D = data index
+ // T = thread
+ // nTpC = number of threads per CTA
+ // nCpS = number of CTA per shader
+ //
+ // for a given local memory address threads in a CTA map to contiguous addresses,
// then distribute across memory space by CTAs from successive shader cores first,
// then by successive CTA in same shader core
- localaddr *= m_config->gpu_padded_cta_size * m_config->gpu_max_cta_per_shader * num_shader;
- localaddr += m_config->gpu_padded_cta_size * (m_sid + num_shader * (tid / m_config->gpu_padded_cta_size));
- localaddr += tid % m_config->gpu_padded_cta_size;
+ thread_base = 4*(kernel_padded_threads_per_cta * (m_sid + num_shader * (tid / kernel_padded_threads_per_cta))
+ + tid % kernel_padded_threads_per_cta);
+ max_concurrent_threads = kernel_padded_threads_per_cta * kernel_max_cta_per_shader * num_shader;
} else {
// legacy mapping that maps the same address in the local memory space of all threads
// to a single contiguous address region
- localaddr *= num_shader * m_config->n_thread_per_shader;
- localaddr += (m_config->n_thread_per_shader *m_sid) + tid;
+ thread_base = 4*(m_config->n_thread_per_shader * m_sid + tid);
+ max_concurrent_threads = num_shader * m_config->n_thread_per_shader;
}
- localaddr *= 4;
+ assert( thread_base < 4/*word size*/*max_concurrent_threads );
- return localaddr;
+ address_type local_word = localaddr/4;
+ address_type word_offset = localaddr%4;
+ address_type linear_address = local_word*max_concurrent_threads + thread_base + word_offset;
+ return linear_address;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -1181,19 +1194,29 @@ void ldst_unit::cycle()
}
}
-void shader_core_ctx::register_cta_thread_exit(int tid )
+void shader_core_ctx::register_cta_thread_exit( unsigned cta_num )
{
- unsigned padded_cta_size = m_gpu->the_kernel().threads_per_cta();
- if (padded_cta_size%m_config->warp_size)
- padded_cta_size = ((padded_cta_size/m_config->warp_size)+1)*(m_config->warp_size);
- int cta_num = tid/padded_cta_size;
assert( m_cta_status[cta_num] > 0 );
m_cta_status[cta_num]--;
if (!m_cta_status[cta_num]) {
m_n_active_cta--;
m_barriers.deallocate_barrier(cta_num);
shader_CTA_count_unlog(m_sid, 1);
- printf("GPGPU-Sim uArch: Shader %d finished CTA #%d (%lld,%lld)\n", m_sid, cta_num, gpu_sim_cycle, gpu_tot_sim_cycle );
+ printf("GPGPU-Sim uArch: Shader %d finished CTA #%d (%lld,%lld), %u CTAs running\n", m_sid, cta_num, gpu_sim_cycle, gpu_tot_sim_cycle,
+ m_n_active_cta );
+ if( m_n_active_cta == 0 ) {
+ assert( m_kernel != NULL );
+ m_kernel->dec_running();
+ printf("GPGPU-Sim uArch: Shader %u empty.\n", m_sid );
+ if( m_kernel->no_more_ctas_to_run() ) {
+ if( !m_kernel->running() ) {
+ m_gpu->set_kernel_done( m_kernel->get_uid() );
+ printf("GPGPU-Sim uArch: GPU detected kernel \'%s\' finished on shader %u.\n", m_kernel->name().c_str(), m_sid );
+ }
+ }
+ m_kernel=NULL;
+ fflush(stdout);
+ }
}
}
@@ -1483,11 +1506,20 @@ unsigned int shader_core_config::max_cta( const kernel_info_t &k ) const
printf ("\n");
}
- if (result < 1) {
- printf ("GPGPU-Sim uArch: ERROR ** Kernel requires more resources than shader has.\n");
- abort();
- }
- return result;
+ //gpu_max_cta_per_shader is limited by number of CTAs if not enough to keep all cores busy
+ if( k.num_blocks() < result*num_shader() ) {
+ result = k.num_blocks() / num_shader();
+ if (k.num_blocks() % num_shader())
+ result++;
+ }
+
+ assert( result <= MAX_CTA_PER_SHADER );
+ if (result < 1) {
+ printf ("GPGPU-Sim uArch: ERROR ** Kernel requires more resources than shader has.\n");
+ abort();
+ }
+
+ return result;
}
void shader_core_ctx::cycle()
@@ -1712,6 +1744,16 @@ bool shader_core_ctx::warp_waiting_at_mem_barrier( unsigned warp_id )
return true;
}
+void shader_core_ctx::set_max_cta( const kernel_info_t &kernel )
+{
+ // calculate the max cta count and cta size for local memory address mapping
+ kernel_max_cta_per_shader = m_config->max_cta(kernel);
+ unsigned int gpu_cta_size = kernel.threads_per_cta();
+ kernel_padded_threads_per_cta = (gpu_cta_size%m_config->warp_size) ?
+ m_config->warp_size*((gpu_cta_size/m_config->warp_size)+1) :
+ gpu_cta_size;
+}
+
gpgpu_sim *shader_core_ctx::get_gpu()
{
return m_gpu;
@@ -2120,13 +2162,21 @@ unsigned simt_core_cluster::get_n_active_cta() const
return n;
}
-unsigned simt_core_cluster::issue_block2core( class kernel_info_t &kernel )
+unsigned simt_core_cluster::issue_block2core()
{
unsigned num_blocks_issued=0;
for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) {
unsigned core = (i+m_cta_issue_next_core+1)%m_config->n_simt_cores_per_cluster;
- if( m_core[core]->get_n_active_cta() < m_config->max_cta(kernel) ) {
- m_core[core]->issue_block2core(kernel);
+ if( m_core[core]->get_not_completed() == 0 ) {
+ if( m_core[core]->get_kernel() == NULL ) {
+ kernel_info_t *k = m_gpu->select_kernel();
+ if( k )
+ m_core[core]->set_kernel(k);
+ }
+ }
+ kernel_info_t *kernel = m_core[core]->get_kernel();
+ if( kernel && !kernel->no_more_ctas_to_run() && (m_core[core]->get_n_active_cta() < m_config->max_cta(*kernel)) ) {
+ m_core[core]->issue_block2core(*kernel);
num_blocks_issued++;
m_cta_issue_next_core=core;
break;
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index 9200c99..7f41cfe 100644
--- a/src/gpgpu-sim/shader.h
+++ b/src/gpgpu-sim/shader.h
@@ -983,11 +983,8 @@ struct shader_core_config : public core_config
unsigned gpgpu_shader_registers;
int gpgpu_warpdistro_shader;
unsigned gpgpu_num_reg_banks;
- unsigned gpu_max_cta_per_shader; // TODO: modify this for fermi... computed based upon kernel
- // resource usage; used in shader_core_ctx::translate_local_memaddr
bool gpgpu_reg_bank_use_warp_id;
bool gpgpu_local_mem_map;
- int gpu_padded_cta_size;
unsigned max_sp_latency;
unsigned max_sfu_latency;
@@ -1122,12 +1119,20 @@ public:
void cache_flush();
void accept_fetch_response( mem_fetch *mf );
void accept_ldst_unit_response( class mem_fetch * mf );
+ void set_kernel( kernel_info_t *k )
+ {
+ assert(k);
+ m_kernel=k;
+ if(k) k->inc_running();
+ printf("GPGPU-Sim uArch: Shader %d kernel = 0x%p\n", m_sid, m_kernel );
+ }
// accessors
bool fetch_unit_response_buffer_full() const;
bool ldst_unit_response_buffer_full() const;
unsigned get_not_completed() const { return m_not_completed; }
unsigned get_n_active_cta() const { return m_n_active_cta; }
+ kernel_info_t *get_kernel() { return m_kernel; }
// used by functional simulation:
// modifiers
@@ -1148,6 +1153,7 @@ public:
void dec_inst_in_pipeline( unsigned warp_id ) { m_warp[warp_id].dec_inst_in_pipeline(); } // also used in writeback()
void store_ack( class mem_fetch *mf );
bool warp_waiting_at_mem_barrier( unsigned warp_id );
+ void set_max_cta( const kernel_info_t &kernel );
// accessors
std::list<unsigned> get_regs_written( const inst_t &fvt ) const;
@@ -1163,7 +1169,7 @@ private:
address_type next_pc( int tid ) const;
void fetch();
- void register_cta_thread_exit(int cta_num );
+ void register_cta_thread_exit( unsigned cta_num );
void decode();
void issue_warp( warp_inst_t *&warp, const warp_inst_t *pI, const active_mask_t &active_mask, unsigned warp_id );
@@ -1189,6 +1195,7 @@ private:
const memory_config *m_memory_config;
class simt_core_cluster *m_cluster;
class gpgpu_sim *m_gpu;
+ kernel_info_t *m_kernel;
// statistics
shader_core_stats *m_stats;
@@ -1228,6 +1235,10 @@ private:
ldst_unit *m_ldst_unit;
static const unsigned MAX_ALU_LATENCY = 64;
std::bitset<MAX_ALU_LATENCY> m_result_bus;
+
+ // used for local address mapping with single kernel launch
+ unsigned kernel_max_cta_per_shader;
+ unsigned kernel_padded_threads_per_cta;
};
class simt_core_cluster {
@@ -1243,7 +1254,7 @@ public:
void icnt_cycle();
void reinit();
- unsigned issue_block2core( class kernel_info_t &kernel );
+ unsigned issue_block2core();
void cache_flush();
bool icnt_injection_buffer_full(unsigned size, bool write);
void icnt_inject_request_packet(class mem_fetch *mf);
diff --git a/src/gpgpu-sim/stat-tool.cc b/src/gpgpu-sim/stat-tool.cc
index 744a39d..576412c 100644
--- a/src/gpgpu-sim/stat-tool.cc
+++ b/src/gpgpu-sim/stat-tool.cc
@@ -152,7 +152,7 @@ unsigned translate_pc_to_ptxlineno(unsigned pc);
static int n_thread_CFloggers = 0;
static thread_CFlocality** thread_CFlogger = NULL;
-void create_thread_CFlogger( int n_loggers, int n_threads, int n_insn, address_type start_pc, unsigned long long logging_interval)
+void create_thread_CFlogger( int n_loggers, int n_threads, address_type start_pc, unsigned long long logging_interval)
{
destroy_thread_CFlogger();
@@ -163,7 +163,7 @@ void create_thread_CFlogger( int n_loggers, int n_threads, int n_insn, address_t
char buffer[32];
for (int i = 0; i < n_thread_CFloggers; i++) {
snprintf(buffer, 32, "%02d", i);
- thread_CFlogger[i] = new thread_CFlocality( name_tpl + buffer, logging_interval, n_threads, n_insn, start_pc);
+ thread_CFlogger[i] = new thread_CFlocality( name_tpl + buffer, logging_interval, n_threads, start_pc);
if (logging_interval != 0) {
add_snap_shot_trigger(thread_CFlogger[i]);
add_spill_log(thread_CFlogger[i]);
@@ -222,10 +222,10 @@ int insn_warp_occ_logger::s_ids = 0;
static std::vector<insn_warp_occ_logger> iwo_logger;
-void insn_warp_occ_create( int n_loggers, int simd_width, int n_insn)
+void insn_warp_occ_create( int n_loggers, int simd_width )
{
iwo_logger.clear();
- iwo_logger.assign(n_loggers, insn_warp_occ_logger(simd_width, n_insn));
+ iwo_logger.assign(n_loggers, insn_warp_occ_logger(simd_width));
for (unsigned i = 0; i < iwo_logger.size(); i++) {
iwo_logger[i].set_id(i);
}
@@ -509,12 +509,12 @@ void shader_CTA_count_visualizer_gzprint( gzFile fout )
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
-thread_insn_span::thread_insn_span(unsigned long long cycle, int n_insn)
- : m_cycle(cycle), m_n_insn(n_insn),
+thread_insn_span::thread_insn_span(unsigned long long cycle)
+ : m_cycle(cycle),
#ifdef USE_MAP
m_insn_span_count()
#else
- m_insn_span_count(n_insn * 2)
+ m_insn_span_count(32*1024)
#endif
{
}
@@ -522,7 +522,7 @@ thread_insn_span::thread_insn_span(unsigned long long cycle, int n_insn)
thread_insn_span::~thread_insn_span() { }
thread_insn_span::thread_insn_span(const thread_insn_span& other)
- : m_cycle(other.m_cycle), m_n_insn(other.m_n_insn),
+ : m_cycle(other.m_cycle),
m_insn_span_count(other.m_insn_span_count)
{
}
@@ -530,8 +530,7 @@ thread_insn_span::thread_insn_span(const thread_insn_span& other)
thread_insn_span& thread_insn_span::operator=(const thread_insn_span& other)
{
printf("thread_insn_span& operator=\n");
- if (this != &other && m_n_insn != other.m_n_insn) {
- m_n_insn = other.m_n_insn;
+ if (this != &other) {
m_insn_span_count = other.m_insn_span_count;
m_cycle = other.m_cycle;
}
@@ -540,7 +539,6 @@ thread_insn_span& thread_insn_span::operator=(const thread_insn_span& other)
thread_insn_span& thread_insn_span::operator+=(const thread_insn_span& other)
{
- assert(m_n_insn == other.m_n_insn); // no way to aggregate if they are different programs
span_count_map::const_iterator i_sc = other.m_insn_span_count.begin();
for (; i_sc != other.m_insn_span_count.end(); ++i_sc) {
m_insn_span_count[i_sc->first] += i_sc->second;
@@ -615,12 +613,11 @@ void thread_insn_span::print_sparse_histo(gzFile fout) const
thread_CFlocality::thread_CFlocality(std::string name,
unsigned long long snap_shot_interval,
int nthreads,
- int n_insn,
address_type start_pc,
unsigned long long start_cycle)
: snap_shot_trigger(snap_shot_interval), m_name(name),
m_nthreads(nthreads), m_thread_pc(nthreads, start_pc), m_cycle(start_cycle),
- m_thd_span(start_cycle, n_insn)
+ m_thd_span(start_cycle)
{
std::fill(m_thread_pc.begin(), m_thread_pc.end(), -1); // so that hw thread with no work assigned will not clobber results
}
diff --git a/src/gpgpu-sim/stat-tool.h b/src/gpgpu-sim/stat-tool.h
index 00b7771..31a1dcb 100644
--- a/src/gpgpu-sim/stat-tool.h
+++ b/src/gpgpu-sim/stat-tool.h
@@ -118,7 +118,7 @@ public:
class thread_insn_span {
public:
- thread_insn_span(unsigned long long cycle, int n_insn);
+ thread_insn_span(unsigned long long cycle);
thread_insn_span(const thread_insn_span& other);
~thread_insn_span();
@@ -135,14 +135,13 @@ public:
private:
typedef my_hash_map<address_type, int> span_count_map;
unsigned long long m_cycle;
- int m_n_insn;
span_count_map m_insn_span_count;
};
class thread_CFlocality : public snap_shot_trigger, public spill_log_interface {
public:
thread_CFlocality(std::string name, unsigned long long snap_shot_interval,
- int nthreads, int n_insn, address_type start_pc, unsigned long long start_cycle = 0);
+ int nthreads, address_type start_pc, unsigned long long start_cycle = 0);
~thread_CFlocality();
void update_thread_pc( int thread_id, address_type pc );
@@ -170,9 +169,9 @@ private:
class insn_warp_occ_logger {
public:
- insn_warp_occ_logger(int simd_width, int n_insn)
+ insn_warp_occ_logger(int simd_width)
: m_simd_width(simd_width),
- m_insn_warp_occ(n_insn, linear_histogram(1, "", m_simd_width)),
+ m_insn_warp_occ(1,linear_histogram(1, "", m_simd_width)),
m_id(s_ids++) {}
insn_warp_occ_logger(const insn_warp_occ_logger& other)
@@ -191,7 +190,9 @@ public:
void set_id(int id) { m_id = id; }
void log(address_type pc, int warp_occ) {
- m_insn_warp_occ[pc].add2bin(warp_occ - 1);
+ if( pc >= m_insn_warp_occ.size() )
+ m_insn_warp_occ.resize(2*pc, linear_histogram(1, "", m_simd_width));
+ m_insn_warp_occ[pc].add2bin(warp_occ - 1);
}
void print(FILE *fout) const
@@ -307,7 +308,7 @@ void try_snap_shot (unsigned long long current_cycle);
void set_spill_interval (unsigned long long interval);
void spill_log_to_file (FILE *fout, int final, unsigned long long current_cycle);
-void create_thread_CFlogger( int n_loggers, int n_threads, int n_insn, address_type start_pc, unsigned long long logging_interval);
+void create_thread_CFlogger( int n_loggers, int n_threads, address_type start_pc, unsigned long long logging_interval);
void destroy_thread_CFlogger( );
void cflog_update_thread_pc( int logger_id, int thread_id, address_type pc );
void cflog_snapshot( int logger_id, unsigned long long cycle );
@@ -316,7 +317,7 @@ void cflog_print_path_expression(FILE *fout);
void cflog_visualizer_print(FILE *fout);
void cflog_visualizer_gzprint(gzFile fout);
-void insn_warp_occ_create( int n_loggers, int simd_width, int n_insn );
+void insn_warp_occ_create( int n_loggers, int simd_width );
void insn_warp_occ_log( int logger_id, address_type pc, int warp_occ );
void insn_warp_occ_print( FILE *fout );