diff options
| author | Nick <[email protected]> | 2019-09-13 05:29:40 -0400 |
|---|---|---|
| committer | Nick <[email protected]> | 2019-09-13 05:29:40 -0400 |
| commit | 26ca8de4a6ec9bfe422a14cbe325a5f257df453b (patch) | |
| tree | ed12425be898e85e01e7a3997a9b8d5efba6ef50 | |
| parent | 8dc1567fa99cfcb7d21a80e55dedfe07aaa359bb (diff) | |
Add src/ director formatting
| -rw-r--r-- | src/abstract_hardware_model.cc | 1935 | ||||
| -rw-r--r-- | src/abstract_hardware_model.h | 2104 | ||||
| -rw-r--r-- | src/debug.cc | 332 | ||||
| -rw-r--r-- | src/debug.h | 91 | ||||
| -rw-r--r-- | src/gpgpusim_entrypoint.cc | 413 | ||||
| -rw-r--r-- | src/gpgpusim_entrypoint.h | 70 | ||||
| -rw-r--r-- | src/option_parser.cc | 824 | ||||
| -rw-r--r-- | src/option_parser.h | 50 | ||||
| -rw-r--r-- | src/statwrapper.cc | 59 | ||||
| -rw-r--r-- | src/statwrapper.h | 14 | ||||
| -rw-r--r-- | src/stream_manager.cc | 738 | ||||
| -rw-r--r-- | src/stream_manager.h | 423 | ||||
| -rw-r--r-- | src/tr1_hash_map.h | 43 | ||||
| -rw-r--r-- | src/trace.cc | 36 | ||||
| -rw-r--r-- | src/trace.h | 73 |
15 files changed, 3632 insertions, 3573 deletions
diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index 07232ee..33a7080 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -7,14 +7,16 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this +// Redistributions in binary form must reproduce the above copyright notice, +// this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -25,1185 +27,1192 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - #include "abstract_hardware_model.h" +#include <sys/stat.h> +#include <algorithm> +#include <iostream> +#include <sstream> +#include "../libcuda/gpgpu_context.h" +#include "cuda-sim/cuda-sim.h" #include "cuda-sim/memory.h" -#include "cuda-sim/ptx_ir.h" #include "cuda-sim/ptx-stats.h" -#include "cuda-sim/cuda-sim.h" +#include "cuda-sim/ptx_ir.h" #include "gpgpu-sim/gpu-sim.h" -#include "option_parser.h" #include "gpgpusim_entrypoint.h" -#include <algorithm> -#include <sys/stat.h> -#include <sstream> -#include <iostream> -#include "../libcuda/gpgpu_context.h" +#include "option_parser.h" -void mem_access_t::init(gpgpu_context* ctx) -{ - gpgpu_ctx = ctx; - m_uid=++(gpgpu_ctx->sm_next_access_uid); - m_addr=0; - m_req_size=0; +void mem_access_t::init(gpgpu_context *ctx) { + gpgpu_ctx = ctx; + m_uid = ++(gpgpu_ctx->sm_next_access_uid); + m_addr = 0; + m_req_size = 0; } -void warp_inst_t::issue( const active_mask_t &mask, unsigned warp_id, unsigned long long cycle, int dynamic_warp_id, int sch_id ) -{ - m_warp_active_mask = mask; - m_warp_issued_mask = mask; - m_uid = ++(m_config->gpgpu_ctx->warp_inst_sm_next_uid); - m_warp_id = warp_id; - m_dynamic_warp_id = dynamic_warp_id; - issue_cycle = cycle; - cycles = initiation_interval; - m_cache_hit=false; - m_empty=false; - m_scheduler_id=sch_id; +void warp_inst_t::issue(const active_mask_t &mask, unsigned warp_id, + unsigned long long cycle, int dynamic_warp_id, + int sch_id) { + m_warp_active_mask = mask; + m_warp_issued_mask = mask; + m_uid = ++(m_config->gpgpu_ctx->warp_inst_sm_next_uid); + m_warp_id = warp_id; + m_dynamic_warp_id = dynamic_warp_id; + issue_cycle = cycle; + cycles = initiation_interval; + m_cache_hit = false; + m_empty = false; + m_scheduler_id = sch_id; } -checkpoint::checkpoint() -{ - - struct stat st = {0}; - - if (stat("checkpoint_files", &st) == -1) { - mkdir("checkpoint_files", 0777); - } +checkpoint::checkpoint() { + struct stat st = {0}; + if (stat("checkpoint_files", &st) == -1) { + mkdir("checkpoint_files", 0777); + } } -void checkpoint::load_global_mem(class memory_space *temp_mem, char * f1name) -{ +void checkpoint::load_global_mem(class memory_space *temp_mem, char *f1name) { + FILE *fp2 = fopen(f1name, "r"); + assert(fp2 != NULL); + char line[128]; /* or other suitable maximum line size */ + unsigned int offset; + while (fgets(line, sizeof line, fp2) != NULL) /* read a line */ + { + unsigned int index; + char *pch; + pch = strtok(line, " "); + if (pch[0] == 'g' || pch[0] == 's' || pch[0] == 'l') { + pch = strtok(NULL, " "); - FILE * fp2 = fopen(f1name, "r"); - assert(fp2!=NULL); - char line [ 128 ]; /* or other suitable maximum line size */ - unsigned int offset ; - while ( fgets ( line, sizeof line, fp2 ) != NULL ) /* read a line */ - { - unsigned int index; - char * pch; - pch = strtok (line," "); - if (pch[0]=='g' || pch[0]=='s' || pch[0]=='l') - { + std::stringstream ss; + ss << std::hex << pch; + ss >> index; - pch = strtok (NULL, " "); - - std::stringstream ss; - ss << std::hex << pch; - ss >> index; - - offset=0; - } - else { - unsigned int data; - std::stringstream ss; - ss << std::hex << pch; - ss >> data; - temp_mem->write_only(offset,index, 4,&data); - offset= offset+4; - } - //fputs ( line, stdout ); /* write the line */ - } - fclose ( fp2 ); + offset = 0; + } else { + unsigned int data; + std::stringstream ss; + ss << std::hex << pch; + ss >> data; + temp_mem->write_only(offset, index, 4, &data); + offset = offset + 4; + } + // fputs ( line, stdout ); /* write the line */ + } + fclose(fp2); } -void checkpoint::store_global_mem(class memory_space * mem, char *fname, char * format) -{ - - FILE * fp3 = fopen(fname, "w"); - assert(fp3!=NULL); - mem->print(format,fp3); - fclose(fp3); +void checkpoint::store_global_mem(class memory_space *mem, char *fname, + char *format) { + FILE *fp3 = fopen(fname, "w"); + assert(fp3 != NULL); + mem->print(format, fp3); + fclose(fp3); } -void move_warp( warp_inst_t *&dst, warp_inst_t *&src ) -{ - assert( dst->empty() ); - warp_inst_t* temp = dst; - dst = src; - src = temp; - src->clear(); +void move_warp(warp_inst_t *&dst, warp_inst_t *&src) { + assert(dst->empty()); + warp_inst_t *temp = dst; + dst = src; + src = temp; + src->clear(); } - -void gpgpu_functional_sim_config::reg_options(class OptionParser * opp) -{ - option_parser_register(opp, "-gpgpu_ptx_use_cuobjdump", OPT_BOOL, - &m_ptx_use_cuobjdump, - "Use cuobjdump to extract ptx and sass from binaries", +void gpgpu_functional_sim_config::reg_options(class OptionParser *opp) { + option_parser_register(opp, "-gpgpu_ptx_use_cuobjdump", OPT_BOOL, + &m_ptx_use_cuobjdump, + "Use cuobjdump to extract ptx and sass from binaries", #if (CUDART_VERSION >= 4000) - "1" + "1" #else - "0" + "0" #endif - ); - option_parser_register(opp, "-gpgpu_experimental_lib_support", OPT_BOOL, - &m_experimental_lib_support, - "Try to extract code from cuda libraries [Broken because of unknown cudaGetExportTable]", - "0"); - option_parser_register(opp, "-checkpoint_option", OPT_INT32, &checkpoint_option, - " checkpointing flag (0 = no checkpoint)", - "0"); - option_parser_register(opp, "-checkpoint_kernel", OPT_INT32, &checkpoint_kernel, - " checkpointing during execution of which kernel (1- 1st kernel)", - "1"); - option_parser_register(opp, "-checkpoint_CTA", OPT_INT32, &checkpoint_CTA, - " checkpointing after # of CTA (< less than total CTA)", - "0"); - option_parser_register(opp, "-resume_option", OPT_INT32, &resume_option, - " resume flag (0 = no resume)", - "0"); - option_parser_register(opp, "-resume_kernel", OPT_INT32, &resume_kernel, - " Resume from which kernel (1= 1st kernel)", - "0"); - option_parser_register(opp, "-resume_CTA", OPT_INT32, &resume_CTA, - " resume from which CTA ", - "0"); - option_parser_register(opp, "-checkpoint_CTA_t", OPT_INT32, &checkpoint_CTA_t, - " resume from which CTA ", - "0"); - option_parser_register(opp, "-checkpoint_insn_Y", OPT_INT32, &checkpoint_insn_Y, - " resume from which CTA ", - "0"); + ); + option_parser_register(opp, "-gpgpu_experimental_lib_support", OPT_BOOL, + &m_experimental_lib_support, + "Try to extract code from cuda libraries [Broken " + "because of unknown cudaGetExportTable]", + "0"); + option_parser_register(opp, "-checkpoint_option", OPT_INT32, + &checkpoint_option, + " checkpointing flag (0 = no checkpoint)", "0"); + option_parser_register( + opp, "-checkpoint_kernel", OPT_INT32, &checkpoint_kernel, + " checkpointing during execution of which kernel (1- 1st kernel)", "1"); + option_parser_register( + opp, "-checkpoint_CTA", OPT_INT32, &checkpoint_CTA, + " checkpointing after # of CTA (< less than total CTA)", "0"); + option_parser_register(opp, "-resume_option", OPT_INT32, &resume_option, + " resume flag (0 = no resume)", "0"); + option_parser_register(opp, "-resume_kernel", OPT_INT32, &resume_kernel, + " Resume from which kernel (1= 1st kernel)", "0"); + option_parser_register(opp, "-resume_CTA", OPT_INT32, &resume_CTA, + " resume from which CTA ", "0"); + option_parser_register(opp, "-checkpoint_CTA_t", OPT_INT32, &checkpoint_CTA_t, + " resume from which CTA ", "0"); + option_parser_register(opp, "-checkpoint_insn_Y", OPT_INT32, + &checkpoint_insn_Y, " resume from which CTA ", "0"); - option_parser_register(opp, "-gpgpu_ptx_convert_to_ptxplus", OPT_BOOL, - &m_ptx_convert_to_ptxplus, - "Convert SASS (native ISA) to ptxplus and run ptxplus", - "0"); - option_parser_register(opp, "-gpgpu_ptx_force_max_capability", OPT_UINT32, - &m_ptx_force_max_capability, - "Force maximum compute capability", - "0"); - option_parser_register(opp, "-gpgpu_ptx_inst_debug_to_file", OPT_BOOL, - &g_ptx_inst_debug_to_file, - "Dump executed instructions' debug information to file", - "0"); - option_parser_register(opp, "-gpgpu_ptx_inst_debug_file", OPT_CSTR, &g_ptx_inst_debug_file, - "Executed instructions' debug output file", - "inst_debug.txt"); - option_parser_register(opp, "-gpgpu_ptx_inst_debug_thread_uid", OPT_INT32, &g_ptx_inst_debug_thread_uid, - "Thread UID for executed instructions' debug output", - "1"); + option_parser_register( + opp, "-gpgpu_ptx_convert_to_ptxplus", OPT_BOOL, &m_ptx_convert_to_ptxplus, + "Convert SASS (native ISA) to ptxplus and run ptxplus", "0"); + option_parser_register(opp, "-gpgpu_ptx_force_max_capability", OPT_UINT32, + &m_ptx_force_max_capability, + "Force maximum compute capability", "0"); + option_parser_register( + opp, "-gpgpu_ptx_inst_debug_to_file", OPT_BOOL, &g_ptx_inst_debug_to_file, + "Dump executed instructions' debug information to file", "0"); + option_parser_register( + opp, "-gpgpu_ptx_inst_debug_file", OPT_CSTR, &g_ptx_inst_debug_file, + "Executed instructions' debug output file", "inst_debug.txt"); + option_parser_register(opp, "-gpgpu_ptx_inst_debug_thread_uid", OPT_INT32, + &g_ptx_inst_debug_thread_uid, + "Thread UID for executed instructions' debug output", + "1"); } -void gpgpu_functional_sim_config::ptx_set_tex_cache_linesize(unsigned linesize) -{ - m_texcache_linesize = linesize; +void gpgpu_functional_sim_config::ptx_set_tex_cache_linesize( + unsigned linesize) { + m_texcache_linesize = linesize; } -gpgpu_t::gpgpu_t( const gpgpu_functional_sim_config &config, gpgpu_context* ctx ) - : m_function_model_config(config) -{ - gpgpu_ctx = ctx; - m_global_mem = new memory_space_impl<8192>("global",64*1024); - - m_tex_mem = new memory_space_impl<8192>("tex",64*1024); - m_surf_mem = new memory_space_impl<8192>("surf",64*1024); +gpgpu_t::gpgpu_t(const gpgpu_functional_sim_config &config, gpgpu_context *ctx) + : m_function_model_config(config) { + gpgpu_ctx = ctx; + m_global_mem = new memory_space_impl<8192>("global", 64 * 1024); + + m_tex_mem = new memory_space_impl<8192>("tex", 64 * 1024); + m_surf_mem = new memory_space_impl<8192>("surf", 64 * 1024); - m_dev_malloc=GLOBAL_HEAP_START; - checkpoint_option = m_function_model_config.get_checkpoint_option(); - checkpoint_kernel = m_function_model_config.get_checkpoint_kernel(); - checkpoint_CTA = m_function_model_config.get_checkpoint_CTA(); - resume_option = m_function_model_config.get_resume_option(); - resume_kernel = m_function_model_config.get_resume_kernel(); - resume_CTA = m_function_model_config.get_resume_CTA(); - checkpoint_CTA_t = m_function_model_config.get_checkpoint_CTA_t(); - checkpoint_insn_Y = m_function_model_config.get_checkpoint_insn_Y(); + m_dev_malloc = GLOBAL_HEAP_START; + checkpoint_option = m_function_model_config.get_checkpoint_option(); + checkpoint_kernel = m_function_model_config.get_checkpoint_kernel(); + checkpoint_CTA = m_function_model_config.get_checkpoint_CTA(); + resume_option = m_function_model_config.get_resume_option(); + resume_kernel = m_function_model_config.get_resume_kernel(); + resume_CTA = m_function_model_config.get_resume_CTA(); + checkpoint_CTA_t = m_function_model_config.get_checkpoint_CTA_t(); + checkpoint_insn_Y = m_function_model_config.get_checkpoint_insn_Y(); - // initialize texture mappings to empty - m_NameToTextureInfo.clear(); - m_NameToCudaArray.clear(); - m_TextureRefToName.clear(); - m_NameToAttribute.clear(); + // initialize texture mappings to empty + m_NameToTextureInfo.clear(); + m_NameToCudaArray.clear(); + m_TextureRefToName.clear(); + m_NameToAttribute.clear(); - if(m_function_model_config.get_ptx_inst_debug_to_file() != 0) - ptx_inst_debug_file = fopen(m_function_model_config.get_ptx_inst_debug_file(), "w"); + if (m_function_model_config.get_ptx_inst_debug_to_file() != 0) + ptx_inst_debug_file = + fopen(m_function_model_config.get_ptx_inst_debug_file(), "w"); - gpu_sim_cycle=0; - gpu_tot_sim_cycle=0; + gpu_sim_cycle = 0; + gpu_tot_sim_cycle = 0; } -address_type line_size_based_tag_func(new_addr_type address, new_addr_type line_size) -{ - //gives the tag for an address based on a given line size - return address & ~(line_size-1); +address_type line_size_based_tag_func(new_addr_type address, + new_addr_type line_size) { + // gives the tag for an address based on a given line size + return address & ~(line_size - 1); } -const char * mem_access_type_str(enum mem_access_type access_type) -{ - #define MA_TUP_BEGIN(X) static const char* access_type_str[] = { - #define MA_TUP(X) #X - #define MA_TUP_END(X) }; - MEM_ACCESS_TYPE_TUP_DEF - #undef MA_TUP_BEGIN - #undef MA_TUP - #undef MA_TUP_END +const char *mem_access_type_str(enum mem_access_type access_type) { +#define MA_TUP_BEGIN(X) static const char *access_type_str[] = { +#define MA_TUP(X) #X +#define MA_TUP_END(X) \ + } \ + ; + MEM_ACCESS_TYPE_TUP_DEF +#undef MA_TUP_BEGIN +#undef MA_TUP +#undef MA_TUP_END - assert(access_type < NUM_MEM_ACCESS_TYPE); + assert(access_type < NUM_MEM_ACCESS_TYPE); - return access_type_str[access_type]; + return access_type_str[access_type]; } - -void warp_inst_t::clear_active( const active_mask_t &inactive ) { - active_mask_t test = m_warp_active_mask; - test &= inactive; - assert( test == inactive ); // verify threads being disabled were active - m_warp_active_mask &= ~inactive; +void warp_inst_t::clear_active(const active_mask_t &inactive) { + active_mask_t test = m_warp_active_mask; + test &= inactive; + assert(test == inactive); // verify threads being disabled were active + m_warp_active_mask &= ~inactive; } -void warp_inst_t::set_not_active( unsigned lane_id ) { - m_warp_active_mask.reset(lane_id); +void warp_inst_t::set_not_active(unsigned lane_id) { + m_warp_active_mask.reset(lane_id); } -void warp_inst_t::set_active( const active_mask_t &active ) { - m_warp_active_mask = active; - if( m_isatomic ) { - for( unsigned i=0; i < m_config->warp_size; i++ ) { - if( !m_warp_active_mask.test(i) ) { - m_per_scalar_thread[i].callback.function = NULL; - m_per_scalar_thread[i].callback.instruction = NULL; - m_per_scalar_thread[i].callback.thread = NULL; - } +void warp_inst_t::set_active(const active_mask_t &active) { + m_warp_active_mask = active; + if (m_isatomic) { + for (unsigned i = 0; i < m_config->warp_size; i++) { + if (!m_warp_active_mask.test(i)) { + m_per_scalar_thread[i].callback.function = NULL; + m_per_scalar_thread[i].callback.instruction = NULL; + m_per_scalar_thread[i].callback.thread = NULL; } - } + } + } } void warp_inst_t::do_atomic(bool forceDo) { - do_atomic( m_warp_active_mask,forceDo ); + do_atomic(m_warp_active_mask, forceDo); } - -void warp_inst_t::do_atomic( const active_mask_t& access_mask,bool forceDo ) { - assert( m_isatomic && (!m_empty||forceDo) ); - for( unsigned i=0; i < m_config->warp_size; i++ ) - { - if( access_mask.test(i) ) - { - dram_callback_t &cb = m_per_scalar_thread[i].callback; - if( cb.thread ) - cb.function(cb.instruction, cb.thread); - } +void warp_inst_t::do_atomic(const active_mask_t &access_mask, bool forceDo) { + assert(m_isatomic && (!m_empty || forceDo)); + for (unsigned i = 0; i < m_config->warp_size; i++) { + if (access_mask.test(i)) { + dram_callback_t &cb = m_per_scalar_thread[i].callback; + if (cb.thread) cb.function(cb.instruction, cb.thread); } + } } -void warp_inst_t::broadcast_barrier_reduction(const active_mask_t& access_mask) -{ - for( unsigned i=0; i < m_config->warp_size; i++ ) - { - if( access_mask.test(i) ) - { - dram_callback_t &cb = m_per_scalar_thread[i].callback; - if( cb.thread ){ - cb.function(cb.instruction, cb.thread); - } - } +void warp_inst_t::broadcast_barrier_reduction( + const active_mask_t &access_mask) { + for (unsigned i = 0; i < m_config->warp_size; i++) { + if (access_mask.test(i)) { + dram_callback_t &cb = m_per_scalar_thread[i].callback; + if (cb.thread) { + cb.function(cb.instruction, cb.thread); + } } + } } -void warp_inst_t::generate_mem_accesses() -{ - if( empty() || op == MEMORY_BARRIER_OP || m_mem_accesses_created ) - return; - if (!((op == LOAD_OP) || (op==TENSOR_CORE_LOAD_OP) || (op == STORE_OP)||(op==TENSOR_CORE_STORE_OP))) - return; - if( m_warp_active_mask.count() == 0 ) - return; // predicated off +void warp_inst_t::generate_mem_accesses() { + if (empty() || op == MEMORY_BARRIER_OP || m_mem_accesses_created) return; + if (!((op == LOAD_OP) || (op == TENSOR_CORE_LOAD_OP) || (op == STORE_OP) || + (op == TENSOR_CORE_STORE_OP))) + return; + if (m_warp_active_mask.count() == 0) return; // predicated off - const size_t starting_queue_size = m_accessq.size(); + const size_t starting_queue_size = m_accessq.size(); - assert( is_load() || is_store() ); - assert( m_per_scalar_thread_valid ); // need address information per thread + assert(is_load() || is_store()); + assert(m_per_scalar_thread_valid); // need address information per thread - bool is_write = is_store(); + bool is_write = is_store(); - mem_access_type access_type; - switch (space.get_type()) { + mem_access_type access_type; + switch (space.get_type()) { case const_space: - case param_space_kernel: - access_type = CONST_ACC_R; - break; - case tex_space: - access_type = TEXTURE_ACC_R; - break; - case global_space: - access_type = is_write? GLOBAL_ACC_W: GLOBAL_ACC_R; - break; + case param_space_kernel: + access_type = CONST_ACC_R; + break; + case tex_space: + access_type = TEXTURE_ACC_R; + break; + case global_space: + access_type = is_write ? GLOBAL_ACC_W : GLOBAL_ACC_R; + break; case local_space: - case param_space_local: - access_type = is_write? LOCAL_ACC_W: LOCAL_ACC_R; - break; - case shared_space: break; - case sstarr_space: break; - default: assert(0); break; - } + case param_space_local: + access_type = is_write ? LOCAL_ACC_W : LOCAL_ACC_R; + break; + case shared_space: + break; + case sstarr_space: + break; + default: + assert(0); + break; + } - // Calculate memory accesses generated by this warp - new_addr_type cache_block_size = 0; // in bytes + // Calculate memory accesses generated by this warp + new_addr_type cache_block_size = 0; // in bytes - switch( space.get_type() ) { + switch (space.get_type()) { case shared_space: case sstarr_space: { - unsigned subwarp_size = m_config->warp_size / m_config->mem_warp_parts; - unsigned total_accesses=0; - for( unsigned subwarp=0; subwarp < m_config->mem_warp_parts; subwarp++ ) { + unsigned subwarp_size = m_config->warp_size / m_config->mem_warp_parts; + unsigned total_accesses = 0; + for (unsigned subwarp = 0; subwarp < m_config->mem_warp_parts; + subwarp++) { + // data structures used per part warp + std::map<unsigned, std::map<new_addr_type, unsigned> > + bank_accs; // bank -> word address -> access count - // data structures used per part warp - std::map<unsigned,std::map<new_addr_type,unsigned> > bank_accs; // bank -> word address -> access count + // step 1: compute accesses to words in banks + for (unsigned thread = subwarp * subwarp_size; + thread < (subwarp + 1) * subwarp_size; thread++) { + if (!active(thread)) continue; + new_addr_type addr = m_per_scalar_thread[thread].memreqaddr[0]; + // FIXME: deferred allocation of shared memory should not accumulate + // across kernel launches + // assert( addr < m_config->gpgpu_shmem_size ); + unsigned bank = m_config->shmem_bank_func(addr); + new_addr_type word = + line_size_based_tag_func(addr, m_config->WORD_SIZE); + bank_accs[bank][word]++; + } - // step 1: compute accesses to words in banks - for( unsigned thread=subwarp*subwarp_size; thread < (subwarp+1)*subwarp_size; thread++ ) { - if( !active(thread) ) - continue; - new_addr_type addr = m_per_scalar_thread[thread].memreqaddr[0]; - //FIXME: deferred allocation of shared memory should not accumulate across kernel launches - //assert( addr < m_config->gpgpu_shmem_size ); - unsigned bank = m_config->shmem_bank_func(addr); - new_addr_type word = line_size_based_tag_func(addr,m_config->WORD_SIZE); - bank_accs[bank][word]++; + if (m_config->shmem_limited_broadcast) { + // step 2: look for and select a broadcast bank/word if one occurs + bool broadcast_detected = false; + new_addr_type broadcast_word = (new_addr_type)-1; + unsigned broadcast_bank = (unsigned)-1; + std::map<unsigned, std::map<new_addr_type, unsigned> >::iterator b; + for (b = bank_accs.begin(); b != bank_accs.end(); b++) { + unsigned bank = b->first; + std::map<new_addr_type, unsigned> &access_set = b->second; + std::map<new_addr_type, unsigned>::iterator w; + for (w = access_set.begin(); w != access_set.end(); ++w) { + if (w->second > 1) { + // found a broadcast + broadcast_detected = true; + broadcast_bank = bank; + broadcast_word = w->first; + break; + } } + if (broadcast_detected) break; + } - if (m_config->shmem_limited_broadcast) { - // step 2: look for and select a broadcast bank/word if one occurs - bool broadcast_detected = false; - new_addr_type broadcast_word=(new_addr_type)-1; - unsigned broadcast_bank=(unsigned)-1; - std::map<unsigned,std::map<new_addr_type,unsigned> >::iterator b; - for( b=bank_accs.begin(); b != bank_accs.end(); b++ ) { - unsigned bank = b->first; - std::map<new_addr_type,unsigned> &access_set = b->second; - std::map<new_addr_type,unsigned>::iterator w; - for( w=access_set.begin(); w != access_set.end(); ++w ) { - if( w->second > 1 ) { - // found a broadcast - broadcast_detected=true; - broadcast_bank=bank; - broadcast_word=w->first; - break; - } - } - if( broadcast_detected ) - break; - } - - // step 3: figure out max bank accesses performed, taking account of broadcast case - unsigned max_bank_accesses=0; - for( b=bank_accs.begin(); b != bank_accs.end(); b++ ) { - unsigned bank_accesses=0; - std::map<new_addr_type,unsigned> &access_set = b->second; - std::map<new_addr_type,unsigned>::iterator w; - for( w=access_set.begin(); w != access_set.end(); ++w ) - bank_accesses += w->second; - if( broadcast_detected && broadcast_bank == b->first ) { - for( w=access_set.begin(); w != access_set.end(); ++w ) { - if( w->first == broadcast_word ) { - unsigned n = w->second; - assert(n > 1); // or this wasn't a broadcast - assert(bank_accesses >= (n-1)); - bank_accesses -= (n-1); - break; - } - } - } - if( bank_accesses > max_bank_accesses ) - max_bank_accesses = bank_accesses; + // step 3: figure out max bank accesses performed, taking account of + // broadcast case + unsigned max_bank_accesses = 0; + for (b = bank_accs.begin(); b != bank_accs.end(); b++) { + unsigned bank_accesses = 0; + std::map<new_addr_type, unsigned> &access_set = b->second; + std::map<new_addr_type, unsigned>::iterator w; + for (w = access_set.begin(); w != access_set.end(); ++w) + bank_accesses += w->second; + if (broadcast_detected && broadcast_bank == b->first) { + for (w = access_set.begin(); w != access_set.end(); ++w) { + if (w->first == broadcast_word) { + unsigned n = w->second; + assert(n > 1); // or this wasn't a broadcast + assert(bank_accesses >= (n - 1)); + bank_accesses -= (n - 1); + break; } + } + } + if (bank_accesses > max_bank_accesses) + max_bank_accesses = bank_accesses; + } - // step 4: accumulate - total_accesses+= max_bank_accesses; - } else { - // step 2: look for the bank with the maximum number of access to different words - unsigned max_bank_accesses=0; - std::map<unsigned,std::map<new_addr_type,unsigned> >::iterator b; - for( b=bank_accs.begin(); b != bank_accs.end(); b++ ) { - max_bank_accesses = std::max(max_bank_accesses, (unsigned)b->second.size()); - } + // step 4: accumulate + total_accesses += max_bank_accesses; + } else { + // step 2: look for the bank with the maximum number of access to + // different words + unsigned max_bank_accesses = 0; + std::map<unsigned, std::map<new_addr_type, unsigned> >::iterator b; + for (b = bank_accs.begin(); b != bank_accs.end(); b++) { + max_bank_accesses = + std::max(max_bank_accesses, (unsigned)b->second.size()); + } - // step 3: accumulate - total_accesses+= max_bank_accesses; - } + // step 3: accumulate + total_accesses += max_bank_accesses; } - assert( total_accesses > 0 && total_accesses <= m_config->warp_size ); - cycles = total_accesses; // shared memory conflicts modeled as larger initiation interval - m_config->gpgpu_ctx->stats->ptx_file_line_stats_add_smem_bank_conflict( pc, total_accesses ); - break; + } + assert(total_accesses > 0 && total_accesses <= m_config->warp_size); + cycles = total_accesses; // shared memory conflicts modeled as larger + // initiation interval + m_config->gpgpu_ctx->stats->ptx_file_line_stats_add_smem_bank_conflict( + pc, total_accesses); + break; } - case tex_space: - cache_block_size = m_config->gpgpu_cache_texl1_linesize; - break; - case const_space: case param_space_kernel: - cache_block_size = m_config->gpgpu_cache_constl1_linesize; - break; + case tex_space: + cache_block_size = m_config->gpgpu_cache_texl1_linesize; + break; + case const_space: + case param_space_kernel: + cache_block_size = m_config->gpgpu_cache_constl1_linesize; + break; - case global_space: case local_space: case param_space_local: - if( m_config->gpgpu_coalesce_arch >= 13) { - if(isatomic()) - memory_coalescing_arch_atomic(is_write, access_type); - else - memory_coalescing_arch(is_write, access_type); - } else abort(); + case global_space: + case local_space: + case param_space_local: + if (m_config->gpgpu_coalesce_arch >= 13) { + if (isatomic()) + memory_coalescing_arch_atomic(is_write, access_type); + else + memory_coalescing_arch(is_write, access_type); + } else + abort(); - break; + break; default: - abort(); - } + abort(); + } - if( cache_block_size ) { - assert( m_accessq.empty() ); - mem_access_byte_mask_t byte_mask; - std::map<new_addr_type,active_mask_t> accesses; // block address -> set of thread offsets in warp - std::map<new_addr_type,active_mask_t>::iterator a; - for( unsigned thread=0; thread < m_config->warp_size; thread++ ) { - if( !active(thread) ) - continue; - new_addr_type addr = m_per_scalar_thread[thread].memreqaddr[0]; - unsigned block_address = line_size_based_tag_func(addr,cache_block_size); - accesses[block_address].set(thread); - unsigned idx = addr-block_address; - for( unsigned i=0; i < data_size; i++ ) - byte_mask.set(idx+i); - } - for( a=accesses.begin(); a != accesses.end(); ++a ) - m_accessq.push_back( mem_access_t(access_type,a->first,cache_block_size,is_write,a->second, byte_mask, mem_access_sector_mask_t(), m_config->gpgpu_ctx)); + if (cache_block_size) { + assert(m_accessq.empty()); + mem_access_byte_mask_t byte_mask; + std::map<new_addr_type, active_mask_t> + accesses; // block address -> set of thread offsets in warp + std::map<new_addr_type, active_mask_t>::iterator a; + for (unsigned thread = 0; thread < m_config->warp_size; thread++) { + if (!active(thread)) continue; + new_addr_type addr = m_per_scalar_thread[thread].memreqaddr[0]; + unsigned block_address = line_size_based_tag_func(addr, cache_block_size); + accesses[block_address].set(thread); + unsigned idx = addr - block_address; + for (unsigned i = 0; i < data_size; i++) byte_mask.set(idx + i); } + for (a = accesses.begin(); a != accesses.end(); ++a) + m_accessq.push_back(mem_access_t( + access_type, a->first, cache_block_size, is_write, a->second, + byte_mask, mem_access_sector_mask_t(), m_config->gpgpu_ctx)); + } - if ( space.get_type() == global_space ) { - m_config->gpgpu_ctx->stats->ptx_file_line_stats_add_uncoalesced_gmem( pc, m_accessq.size() - starting_queue_size ); - } - m_mem_accesses_created=true; + if (space.get_type() == global_space) { + m_config->gpgpu_ctx->stats->ptx_file_line_stats_add_uncoalesced_gmem( + pc, m_accessq.size() - starting_queue_size); + } + m_mem_accesses_created = true; } -void warp_inst_t::memory_coalescing_arch( bool is_write, mem_access_type access_type ) -{ - // see the CUDA manual where it discusses coalescing rules before reading this - unsigned segment_size = 0; - unsigned warp_parts = m_config->mem_warp_parts; - bool sector_segment_size = false; +void warp_inst_t::memory_coalescing_arch(bool is_write, + mem_access_type access_type) { + // see the CUDA manual where it discusses coalescing rules before reading this + unsigned segment_size = 0; + unsigned warp_parts = m_config->mem_warp_parts; + bool sector_segment_size = false; - if(m_config->gpgpu_coalesce_arch >= 20 && m_config->gpgpu_coalesce_arch < 39) - { - //Fermi and Kepler, L1 is normal and L2 is sector - if(m_config->gmem_skip_L1D || cache_op == CACHE_GLOBAL) - sector_segment_size = true; - else - sector_segment_size = false; - } - else if(m_config->gpgpu_coalesce_arch >= 40) - { - //Maxwell, Pascal and Volta, L1 and L2 are sectors - //all requests should be 32 bytes - sector_segment_size = true; - } - - switch( data_size ) { - case 1: segment_size = 32; break; - case 2: segment_size = sector_segment_size? 32 : 64; break; - case 4: case 8: case 16: segment_size = sector_segment_size? 32 : 128; break; - } - unsigned subwarp_size = m_config->warp_size / warp_parts; + if (m_config->gpgpu_coalesce_arch >= 20 && + m_config->gpgpu_coalesce_arch < 39) { + // Fermi and Kepler, L1 is normal and L2 is sector + if (m_config->gmem_skip_L1D || cache_op == CACHE_GLOBAL) + sector_segment_size = true; + else + sector_segment_size = false; + } else if (m_config->gpgpu_coalesce_arch >= 40) { + // Maxwell, Pascal and Volta, L1 and L2 are sectors + // all requests should be 32 bytes + sector_segment_size = true; + } - for( unsigned subwarp=0; subwarp < warp_parts; subwarp++ ) { - std::map<new_addr_type,transaction_info> subwarp_transactions; + switch (data_size) { + case 1: + segment_size = 32; + break; + case 2: + segment_size = sector_segment_size ? 32 : 64; + break; + case 4: + case 8: + case 16: + segment_size = sector_segment_size ? 32 : 128; + break; + } + unsigned subwarp_size = m_config->warp_size / warp_parts; - // step 1: find all transactions generated by this subwarp - for( unsigned thread=subwarp*subwarp_size; thread<subwarp_size*(subwarp+1); thread++ ) { - if( !active(thread) ) - continue; + for (unsigned subwarp = 0; subwarp < warp_parts; subwarp++) { + std::map<new_addr_type, transaction_info> subwarp_transactions; - unsigned data_size_coales = data_size; - unsigned num_accesses = 1; + // step 1: find all transactions generated by this subwarp + for (unsigned thread = subwarp * subwarp_size; + thread < subwarp_size * (subwarp + 1); thread++) { + if (!active(thread)) continue; - if( space.get_type() == local_space || space.get_type() == param_space_local ) { - // Local memory accesses >4B were split into 4B chunks - if(data_size >= 4) { - data_size_coales = 4; - num_accesses = data_size/4; - } - // Otherwise keep the same data_size for sub-4B access to local memory - } + unsigned data_size_coales = data_size; + unsigned num_accesses = 1; + if (space.get_type() == local_space || + space.get_type() == param_space_local) { + // Local memory accesses >4B were split into 4B chunks + if (data_size >= 4) { + data_size_coales = 4; + num_accesses = data_size / 4; + } + // Otherwise keep the same data_size for sub-4B access to local memory + } - assert(num_accesses <= MAX_ACCESSES_PER_INSN_PER_THREAD); + assert(num_accesses <= MAX_ACCESSES_PER_INSN_PER_THREAD); -// for(unsigned access=0; access<num_accesses; access++) { - for(unsigned access=0; (access<MAX_ACCESSES_PER_INSN_PER_THREAD)&&(m_per_scalar_thread[thread].memreqaddr[access]!=0); access++) { - new_addr_type addr = m_per_scalar_thread[thread].memreqaddr[access]; - unsigned block_address = line_size_based_tag_func(addr,segment_size); - unsigned chunk = (addr&127)/32; // which 32-byte chunk within in a 128-byte chunk does this thread access? - transaction_info &info = subwarp_transactions[block_address]; + // for(unsigned access=0; access<num_accesses; access++) { + for (unsigned access = 0; + (access < MAX_ACCESSES_PER_INSN_PER_THREAD) && + (m_per_scalar_thread[thread].memreqaddr[access] != 0); + access++) { + new_addr_type addr = m_per_scalar_thread[thread].memreqaddr[access]; + unsigned block_address = line_size_based_tag_func(addr, segment_size); + unsigned chunk = (addr & 127) / 32; // which 32-byte chunk within in a + // 128-byte chunk does this thread + // access? + transaction_info &info = subwarp_transactions[block_address]; - // can only write to one segment - assert(block_address == line_size_based_tag_func(addr+data_size_coales-1,segment_size)); + // can only write to one segment + assert(block_address == line_size_based_tag_func( + addr + data_size_coales - 1, segment_size)); - info.chunks.set(chunk); - info.active.set(thread); - unsigned idx = (addr&127); - for( unsigned i=0; i < data_size_coales; i++ ) - info.bytes.set(idx+i); - } - } - - // step 2: reduce each transaction size, if possible - std::map< new_addr_type, transaction_info >::iterator t; - for( t=subwarp_transactions.begin(); t !=subwarp_transactions.end(); t++ ) { - new_addr_type addr = t->first; - const transaction_info &info = t->second; + info.chunks.set(chunk); + info.active.set(thread); + unsigned idx = (addr & 127); + for (unsigned i = 0; i < data_size_coales; i++) info.bytes.set(idx + i); + } + } - memory_coalescing_arch_reduce_and_send(is_write, access_type, info, addr, segment_size); + // step 2: reduce each transaction size, if possible + std::map<new_addr_type, transaction_info>::iterator t; + for (t = subwarp_transactions.begin(); t != subwarp_transactions.end(); + t++) { + new_addr_type addr = t->first; + const transaction_info &info = t->second; - } + memory_coalescing_arch_reduce_and_send(is_write, access_type, info, addr, + segment_size); } + } } -void warp_inst_t::memory_coalescing_arch_atomic( bool is_write, mem_access_type access_type ) -{ +void warp_inst_t::memory_coalescing_arch_atomic(bool is_write, + mem_access_type access_type) { + assert(space.get_type() == + global_space); // Atomics allowed only for global memory - assert(space.get_type() == global_space); // Atomics allowed only for global memory + // see the CUDA manual where it discusses coalescing rules before reading this + unsigned segment_size = 0; + unsigned warp_parts = m_config->mem_warp_parts; + bool sector_segment_size = false; - // see the CUDA manual where it discusses coalescing rules before reading this - unsigned segment_size = 0; - unsigned warp_parts = m_config->mem_warp_parts; - bool sector_segment_size = false; - - if(m_config->gpgpu_coalesce_arch >= 20 && m_config->gpgpu_coalesce_arch < 39) - { - //Fermi and Kepler, L1 is normal and L2 is sector - if(m_config->gmem_skip_L1D || cache_op == CACHE_GLOBAL) - sector_segment_size = true; - else - sector_segment_size = false; - } - else if(m_config->gpgpu_coalesce_arch >= 40) - { - //Maxwell, Pascal and Volta, L1 and L2 are sectors - //all requests should be 32 bytes - sector_segment_size = true; - } + if (m_config->gpgpu_coalesce_arch >= 20 && + m_config->gpgpu_coalesce_arch < 39) { + // Fermi and Kepler, L1 is normal and L2 is sector + if (m_config->gmem_skip_L1D || cache_op == CACHE_GLOBAL) + sector_segment_size = true; + else + sector_segment_size = false; + } else if (m_config->gpgpu_coalesce_arch >= 40) { + // Maxwell, Pascal and Volta, L1 and L2 are sectors + // all requests should be 32 bytes + sector_segment_size = true; + } - switch( data_size ) { - case 1: segment_size = 32; break; - case 2: segment_size = sector_segment_size? 32 : 64; break; - case 4: case 8: case 16: segment_size = sector_segment_size? 32 : 128; break; - } - unsigned subwarp_size = m_config->warp_size / warp_parts; + switch (data_size) { + case 1: + segment_size = 32; + break; + case 2: + segment_size = sector_segment_size ? 32 : 64; + break; + case 4: + case 8: + case 16: + segment_size = sector_segment_size ? 32 : 128; + break; + } + unsigned subwarp_size = m_config->warp_size / warp_parts; - for( unsigned subwarp=0; subwarp < warp_parts; subwarp++ ) { - std::map<new_addr_type,std::list<transaction_info> > subwarp_transactions; // each block addr maps to a list of transactions + for (unsigned subwarp = 0; subwarp < warp_parts; subwarp++) { + std::map<new_addr_type, std::list<transaction_info> > + subwarp_transactions; // each block addr maps to a list of transactions - // step 1: find all transactions generated by this subwarp - for( unsigned thread=subwarp*subwarp_size; thread<subwarp_size*(subwarp+1); thread++ ) { - if( !active(thread) ) - continue; + // step 1: find all transactions generated by this subwarp + for (unsigned thread = subwarp * subwarp_size; + thread < subwarp_size * (subwarp + 1); thread++) { + if (!active(thread)) continue; - new_addr_type addr = m_per_scalar_thread[thread].memreqaddr[0]; - unsigned block_address = line_size_based_tag_func(addr,segment_size); - unsigned chunk = (addr&127)/32; // which 32-byte chunk within in a 128-byte chunk does this thread access? + new_addr_type addr = m_per_scalar_thread[thread].memreqaddr[0]; + unsigned block_address = line_size_based_tag_func(addr, segment_size); + unsigned chunk = (addr & 127) / 32; // which 32-byte chunk within in a + // 128-byte chunk does this thread + // access? - // can only write to one segment - assert(block_address == line_size_based_tag_func(addr+data_size-1,segment_size)); + // can only write to one segment + assert(block_address == + line_size_based_tag_func(addr + data_size - 1, segment_size)); - // Find a transaction that does not conflict with this thread's accesses - bool new_transaction = true; - std::list<transaction_info>::iterator it; - transaction_info* info; - for(it=subwarp_transactions[block_address].begin(); it!=subwarp_transactions[block_address].end(); it++) { - unsigned idx = (addr&127); - if(not it->test_bytes(idx,idx+data_size-1)) { - new_transaction = false; - info = &(*it); - break; - } - } - if(new_transaction) { - // Need a new transaction - subwarp_transactions[block_address].push_back(transaction_info()); - info = &subwarp_transactions[block_address].back(); - } - assert(info); + // Find a transaction that does not conflict with this thread's accesses + bool new_transaction = true; + std::list<transaction_info>::iterator it; + transaction_info *info; + for (it = subwarp_transactions[block_address].begin(); + it != subwarp_transactions[block_address].end(); it++) { + unsigned idx = (addr & 127); + if (not it->test_bytes(idx, idx + data_size - 1)) { + new_transaction = false; + info = &(*it); + break; + } + } + if (new_transaction) { + // Need a new transaction + subwarp_transactions[block_address].push_back(transaction_info()); + info = &subwarp_transactions[block_address].back(); + } + assert(info); - info->chunks.set(chunk); - info->active.set(thread); - unsigned idx = (addr&127); - for( unsigned i=0; i < data_size; i++ ) { - assert(!info->bytes.test(idx+i)); - info->bytes.set(idx+i); - } - } + info->chunks.set(chunk); + info->active.set(thread); + unsigned idx = (addr & 127); + for (unsigned i = 0; i < data_size; i++) { + assert(!info->bytes.test(idx + i)); + info->bytes.set(idx + i); + } + } - // step 2: reduce each transaction size, if possible - std::map< new_addr_type, std::list<transaction_info> >::iterator t_list; - for( t_list=subwarp_transactions.begin(); t_list !=subwarp_transactions.end(); t_list++ ) { - // For each block addr - new_addr_type addr = t_list->first; - const std::list<transaction_info>& transaction_list = t_list->second; + // step 2: reduce each transaction size, if possible + std::map<new_addr_type, std::list<transaction_info> >::iterator t_list; + for (t_list = subwarp_transactions.begin(); + t_list != subwarp_transactions.end(); t_list++) { + // For each block addr + new_addr_type addr = t_list->first; + const std::list<transaction_info> &transaction_list = t_list->second; - std::list<transaction_info>::const_iterator t; - for(t=transaction_list.begin(); t!=transaction_list.end(); t++) { - // For each transaction - const transaction_info &info = *t; - memory_coalescing_arch_reduce_and_send(is_write, access_type, info, addr, segment_size); - } - } - } + std::list<transaction_info>::const_iterator t; + for (t = transaction_list.begin(); t != transaction_list.end(); t++) { + // For each transaction + const transaction_info &info = *t; + memory_coalescing_arch_reduce_and_send(is_write, access_type, info, + addr, segment_size); + } + } + } } -void warp_inst_t::memory_coalescing_arch_reduce_and_send( bool is_write, mem_access_type access_type, const transaction_info &info, new_addr_type addr, unsigned segment_size ) -{ - assert( (addr & (segment_size-1)) == 0 ); +void warp_inst_t::memory_coalescing_arch_reduce_and_send( + bool is_write, mem_access_type access_type, const transaction_info &info, + new_addr_type addr, unsigned segment_size) { + assert((addr & (segment_size - 1)) == 0); - const std::bitset<4> &q = info.chunks; - assert( q.count() >= 1 ); - std::bitset<2> h; // halves (used to check if 64 byte segment can be compressed into a single 32 byte segment) + const std::bitset<4> &q = info.chunks; + assert(q.count() >= 1); + std::bitset<2> h; // halves (used to check if 64 byte segment can be + // compressed into a single 32 byte segment) - unsigned size=segment_size; - if( segment_size == 128 ) { - bool lower_half_used = q[0] || q[1]; - bool upper_half_used = q[2] || q[3]; - if( lower_half_used && !upper_half_used ) { - // only lower 64 bytes used - size = 64; - if(q[0]) h.set(0); - if(q[1]) h.set(1); - } else if ( (!lower_half_used) && upper_half_used ) { - // only upper 64 bytes used - addr = addr+64; - size = 64; - if(q[2]) h.set(0); - if(q[3]) h.set(1); - } else { - assert(lower_half_used && upper_half_used); - } - } else if( segment_size == 64 ) { - // need to set halves - if( (addr % 128) == 0 ) { - if(q[0]) h.set(0); - if(q[1]) h.set(1); - } else { - assert( (addr % 128) == 64 ); - if(q[2]) h.set(0); - if(q[3]) h.set(1); - } - } - if( size == 64 ) { - bool lower_half_used = h[0]; - bool upper_half_used = h[1]; - if( lower_half_used && !upper_half_used ) { - size = 32; - } else if ( (!lower_half_used) && upper_half_used ) { - addr = addr+32; - size = 32; - } else { - assert(lower_half_used && upper_half_used); - } - } - m_accessq.push_back( mem_access_t(access_type,addr,size,is_write,info.active,info.bytes, info.chunks,m_config->gpgpu_ctx) ); + unsigned size = segment_size; + if (segment_size == 128) { + bool lower_half_used = q[0] || q[1]; + bool upper_half_used = q[2] || q[3]; + if (lower_half_used && !upper_half_used) { + // only lower 64 bytes used + size = 64; + if (q[0]) h.set(0); + if (q[1]) h.set(1); + } else if ((!lower_half_used) && upper_half_used) { + // only upper 64 bytes used + addr = addr + 64; + size = 64; + if (q[2]) h.set(0); + if (q[3]) h.set(1); + } else { + assert(lower_half_used && upper_half_used); + } + } else if (segment_size == 64) { + // need to set halves + if ((addr % 128) == 0) { + if (q[0]) h.set(0); + if (q[1]) h.set(1); + } else { + assert((addr % 128) == 64); + if (q[2]) h.set(0); + if (q[3]) h.set(1); + } + } + if (size == 64) { + bool lower_half_used = h[0]; + bool upper_half_used = h[1]; + if (lower_half_used && !upper_half_used) { + size = 32; + } else if ((!lower_half_used) && upper_half_used) { + addr = addr + 32; + size = 32; + } else { + assert(lower_half_used && upper_half_used); + } + } + m_accessq.push_back(mem_access_t(access_type, addr, size, is_write, + info.active, info.bytes, info.chunks, + m_config->gpgpu_ctx)); } -void warp_inst_t::completed( unsigned long long cycle ) const -{ - unsigned long long latency = cycle - issue_cycle; - assert(latency <= cycle); // underflow detection - m_config->gpgpu_ctx->stats->ptx_file_line_stats_add_latency(pc, latency * active_count()); +void warp_inst_t::completed(unsigned long long cycle) const { + unsigned long long latency = cycle - issue_cycle; + assert(latency <= cycle); // underflow detection + m_config->gpgpu_ctx->stats->ptx_file_line_stats_add_latency( + pc, latency * active_count()); } +kernel_info_t::kernel_info_t(dim3 gridDim, dim3 blockDim, + class function_info *entry) { + m_kernel_entry = entry; + m_grid_dim = gridDim; + m_block_dim = blockDim; + m_next_cta.x = 0; + m_next_cta.y = 0; + m_next_cta.z = 0; + m_next_tid = m_next_cta; + m_num_cores_running = 0; + m_uid = (entry->gpgpu_ctx->kernel_info_m_next_uid)++; + m_param_mem = new memory_space_impl<8192>("param", 64 * 1024); -kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry) -{ - m_kernel_entry=entry; - m_grid_dim=gridDim; - m_block_dim=blockDim; - m_next_cta.x=0; - m_next_cta.y=0; - m_next_cta.z=0; - m_next_tid=m_next_cta; - m_num_cores_running=0; - m_uid = (entry->gpgpu_ctx->kernel_info_m_next_uid)++; - m_param_mem = new memory_space_impl<8192>("param",64*1024); + // Jin: parent and child kernel management for CDP + m_parent_kernel = NULL; - //Jin: parent and child kernel management for CDP - m_parent_kernel = NULL; + // Jin: launch latency management + m_launch_latency = entry->gpgpu_ctx->device_runtime->g_kernel_launch_latency; - //Jin: launch latency management - m_launch_latency = entry->gpgpu_ctx->device_runtime->g_kernel_launch_latency; - - volta_cache_config_set=false; + volta_cache_config_set = false; } -/*A snapshot of the texture mappings needs to be stored in the kernel's info as +/*A snapshot of the texture mappings needs to be stored in the kernel's info as kernels should use the texture bindings seen at the time of launch and textures can be bound/unbound asynchronously with respect to streams. */ -kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map<std::string, const struct cudaArray*> nameToCudaArray, std::map<std::string, const struct textureInfo*> nameToTextureInfo) -{ - m_kernel_entry=entry; - m_grid_dim=gridDim; - m_block_dim=blockDim; - m_next_cta.x=0; - m_next_cta.y=0; - m_next_cta.z=0; - m_next_tid=m_next_cta; - m_num_cores_running=0; - m_uid = (entry->gpgpu_ctx->kernel_info_m_next_uid)++; - m_param_mem = new memory_space_impl<8192>("param",64*1024); +kernel_info_t::kernel_info_t( + dim3 gridDim, dim3 blockDim, class function_info *entry, + std::map<std::string, const struct cudaArray *> nameToCudaArray, + std::map<std::string, const struct textureInfo *> nameToTextureInfo) { + m_kernel_entry = entry; + m_grid_dim = gridDim; + m_block_dim = blockDim; + m_next_cta.x = 0; + m_next_cta.y = 0; + m_next_cta.z = 0; + m_next_tid = m_next_cta; + m_num_cores_running = 0; + m_uid = (entry->gpgpu_ctx->kernel_info_m_next_uid)++; + m_param_mem = new memory_space_impl<8192>("param", 64 * 1024); - //Jin: parent and child kernel management for CDP - m_parent_kernel = NULL; - - //Jin: launch latency management - m_launch_latency = entry->gpgpu_ctx->device_runtime->g_kernel_launch_latency; + // Jin: parent and child kernel management for CDP + m_parent_kernel = NULL; - volta_cache_config_set=false; - m_NameToCudaArray = nameToCudaArray; - m_NameToTextureInfo = nameToTextureInfo; -} + // Jin: launch latency management + m_launch_latency = entry->gpgpu_ctx->device_runtime->g_kernel_launch_latency; -kernel_info_t::~kernel_info_t() -{ - assert( m_active_threads.empty() ); - destroy_cta_streams(); - delete m_param_mem; + volta_cache_config_set = false; + m_NameToCudaArray = nameToCudaArray; + m_NameToTextureInfo = nameToTextureInfo; } -std::string kernel_info_t::name() const -{ - return m_kernel_entry->get_name(); +kernel_info_t::~kernel_info_t() { + assert(m_active_threads.empty()); + destroy_cta_streams(); + delete m_param_mem; } -//Jin: parent and child kernel management for CDP -void kernel_info_t::set_parent(kernel_info_t * parent, - dim3 parent_ctaid, dim3 parent_tid) { - m_parent_kernel = parent; - m_parent_ctaid = parent_ctaid; - m_parent_tid = parent_tid; - parent->set_child(this); +std::string kernel_info_t::name() const { return m_kernel_entry->get_name(); } + +// Jin: parent and child kernel management for CDP +void kernel_info_t::set_parent(kernel_info_t *parent, dim3 parent_ctaid, + dim3 parent_tid) { + m_parent_kernel = parent; + m_parent_ctaid = parent_ctaid; + m_parent_tid = parent_tid; + parent->set_child(this); } -void kernel_info_t::set_child(kernel_info_t * child) { - m_child_kernels.push_back(child); +void kernel_info_t::set_child(kernel_info_t *child) { + m_child_kernels.push_back(child); } -void kernel_info_t::remove_child(kernel_info_t * child) { - assert(std::find(m_child_kernels.begin(), m_child_kernels.end(), child) - != m_child_kernels.end()); - m_child_kernels.remove(child); +void kernel_info_t::remove_child(kernel_info_t *child) { + assert(std::find(m_child_kernels.begin(), m_child_kernels.end(), child) != + m_child_kernels.end()); + m_child_kernels.remove(child); } bool kernel_info_t::is_finished() { - if(done() && children_all_finished()) - return true; + if (done() && children_all_finished()) + return true; else - return false; + return false; } bool kernel_info_t::children_all_finished() { - if(!m_child_kernels.empty()) - return false; - - return true; + if (!m_child_kernels.empty()) return false; + + return true; } void kernel_info_t::notify_parent_finished() { - if(m_parent_kernel) { - m_kernel_entry->gpgpu_ctx->device_runtime->g_total_param_size -= ((m_kernel_entry->get_args_aligned_size() + 255)/256*256); - m_parent_kernel->remove_child(this); - m_kernel_entry->gpgpu_ctx->the_gpgpusim->g_stream_manager->register_finished_kernel(m_parent_kernel->get_uid()); - } + if (m_parent_kernel) { + m_kernel_entry->gpgpu_ctx->device_runtime->g_total_param_size -= + ((m_kernel_entry->get_args_aligned_size() + 255) / 256 * 256); + m_parent_kernel->remove_child(this); + m_kernel_entry->gpgpu_ctx->the_gpgpusim->g_stream_manager + ->register_finished_kernel(m_parent_kernel->get_uid()); + } } -CUstream_st * kernel_info_t::create_stream_cta(dim3 ctaid) { - assert(get_default_stream_cta(ctaid)); - CUstream_st * stream = new CUstream_st(); - m_kernel_entry->gpgpu_ctx->the_gpgpusim->g_stream_manager->add_stream(stream); - assert(m_cta_streams.find(ctaid) != m_cta_streams.end()); - assert(m_cta_streams[ctaid].size() >= 1); //must have default stream - m_cta_streams[ctaid].push_back(stream); +CUstream_st *kernel_info_t::create_stream_cta(dim3 ctaid) { + assert(get_default_stream_cta(ctaid)); + CUstream_st *stream = new CUstream_st(); + m_kernel_entry->gpgpu_ctx->the_gpgpusim->g_stream_manager->add_stream(stream); + assert(m_cta_streams.find(ctaid) != m_cta_streams.end()); + assert(m_cta_streams[ctaid].size() >= 1); // must have default stream + m_cta_streams[ctaid].push_back(stream); - return stream; + return stream; } -CUstream_st * kernel_info_t::get_default_stream_cta(dim3 ctaid) { - if(m_cta_streams.find(ctaid) != m_cta_streams.end()) { - assert(m_cta_streams[ctaid].size() >= 1); //already created, must have default stream - return *(m_cta_streams[ctaid].begin()); - } - else { - m_cta_streams[ctaid] = std::list<CUstream_st *>(); - CUstream_st * stream = new CUstream_st(); - m_kernel_entry->gpgpu_ctx->the_gpgpusim->g_stream_manager->add_stream(stream); - m_cta_streams[ctaid].push_back(stream); - return stream; - } +CUstream_st *kernel_info_t::get_default_stream_cta(dim3 ctaid) { + if (m_cta_streams.find(ctaid) != m_cta_streams.end()) { + assert(m_cta_streams[ctaid].size() >= + 1); // already created, must have default stream + return *(m_cta_streams[ctaid].begin()); + } else { + m_cta_streams[ctaid] = std::list<CUstream_st *>(); + CUstream_st *stream = new CUstream_st(); + m_kernel_entry->gpgpu_ctx->the_gpgpusim->g_stream_manager->add_stream( + stream); + m_cta_streams[ctaid].push_back(stream); + return stream; + } } -bool kernel_info_t::cta_has_stream(dim3 ctaid, CUstream_st* stream) { - if(m_cta_streams.find(ctaid) == m_cta_streams.end()) - return false; +bool kernel_info_t::cta_has_stream(dim3 ctaid, CUstream_st *stream) { + if (m_cta_streams.find(ctaid) == m_cta_streams.end()) return false; - std::list<CUstream_st *> &stream_list = m_cta_streams[ctaid]; - if(std::find(stream_list.begin(), stream_list.end(), stream) - == stream_list.end()) - return false; - else - return true; + std::list<CUstream_st *> &stream_list = m_cta_streams[ctaid]; + if (std::find(stream_list.begin(), stream_list.end(), stream) == + stream_list.end()) + return false; + else + return true; } void kernel_info_t::print_parent_info() { - if(m_parent_kernel) { - printf("Parent %d: \'%s\', Block (%d, %d, %d), Thread (%d, %d, %d)\n", - m_parent_kernel->get_uid(), m_parent_kernel->name().c_str(), - m_parent_ctaid.x, m_parent_ctaid.y, m_parent_ctaid.z, - m_parent_tid.x, m_parent_tid.y, m_parent_tid.z); - } + if (m_parent_kernel) { + printf("Parent %d: \'%s\', Block (%d, %d, %d), Thread (%d, %d, %d)\n", + m_parent_kernel->get_uid(), m_parent_kernel->name().c_str(), + m_parent_ctaid.x, m_parent_ctaid.y, m_parent_ctaid.z, m_parent_tid.x, + m_parent_tid.y, m_parent_tid.z); + } } void kernel_info_t::destroy_cta_streams() { - printf("Destroy streams for kernel %d: ", get_uid()); size_t stream_size = 0; - for(auto s = m_cta_streams.begin(); s != m_cta_streams.end(); s++) { - stream_size += s->second.size(); - for(auto ss = s->second.begin(); ss != s->second.end(); ss++) - m_kernel_entry->gpgpu_ctx->the_gpgpusim->g_stream_manager->destroy_stream(*ss); - s->second.clear(); - } - printf("size %lu\n", stream_size); - m_cta_streams.clear(); + printf("Destroy streams for kernel %d: ", get_uid()); + size_t stream_size = 0; + for (auto s = m_cta_streams.begin(); s != m_cta_streams.end(); s++) { + stream_size += s->second.size(); + for (auto ss = s->second.begin(); ss != s->second.end(); ss++) + m_kernel_entry->gpgpu_ctx->the_gpgpusim->g_stream_manager->destroy_stream( + *ss); + s->second.clear(); + } + printf("size %lu\n", stream_size); + m_cta_streams.clear(); } -simt_stack::simt_stack( unsigned wid, unsigned warpSize, class gpgpu_sim * gpu) -{ - m_warp_id=wid; - m_warp_size = warpSize; - m_gpu=gpu; - reset(); +simt_stack::simt_stack(unsigned wid, unsigned warpSize, class gpgpu_sim *gpu) { + m_warp_id = wid; + m_warp_size = warpSize; + m_gpu = gpu; + reset(); } -void simt_stack::reset() -{ - m_stack.clear(); -} +void simt_stack::reset() { m_stack.clear(); } -void simt_stack::launch( address_type start_pc, const simt_mask_t &active_mask ) -{ - reset(); - simt_stack_entry new_stack_entry; - new_stack_entry.m_pc = start_pc; - new_stack_entry.m_calldepth = 1; - new_stack_entry.m_active_mask = active_mask; - new_stack_entry.m_type = STACK_ENTRY_TYPE_NORMAL; - m_stack.push_back(new_stack_entry); +void simt_stack::launch(address_type start_pc, const simt_mask_t &active_mask) { + reset(); + simt_stack_entry new_stack_entry; + new_stack_entry.m_pc = start_pc; + new_stack_entry.m_calldepth = 1; + new_stack_entry.m_active_mask = active_mask; + new_stack_entry.m_type = STACK_ENTRY_TYPE_NORMAL; + m_stack.push_back(new_stack_entry); } -void simt_stack::resume( char * fname ) -{ - reset(); - - +void simt_stack::resume(char *fname) { + reset(); - FILE * fp2 = fopen(fname, "r"); - assert(fp2!=NULL); + FILE *fp2 = fopen(fname, "r"); + assert(fp2 != NULL); - char line [ 200 ]; /* or other suitable maximum line size */ + char line[200]; /* or other suitable maximum line size */ - while ( fgets ( line, sizeof line, fp2 ) != NULL ) /* read a line */ - { - simt_stack_entry new_stack_entry; - char * pch; - pch = strtok (line," "); - for (unsigned j=0; j<m_warp_size; j++) - { - if (pch[0]=='1') - new_stack_entry.m_active_mask.set(j); - else - new_stack_entry.m_active_mask.reset(j); - pch = strtok (NULL," "); - - } - - new_stack_entry.m_pc=atoi(pch); - pch = strtok (NULL," "); - new_stack_entry.m_calldepth=atoi(pch); - pch = strtok (NULL," "); - new_stack_entry.m_recvg_pc=atoi(pch); - pch = strtok (NULL," "); - new_stack_entry.m_branch_div_cycle=atoi(pch); - pch = strtok (NULL," "); - if(pch[0]=='0') - new_stack_entry.m_type= STACK_ENTRY_TYPE_NORMAL; - else - new_stack_entry.m_type= STACK_ENTRY_TYPE_CALL; - m_stack.push_back(new_stack_entry); - } - fclose ( fp2 ); + while (fgets(line, sizeof line, fp2) != NULL) /* read a line */ + { + simt_stack_entry new_stack_entry; + char *pch; + pch = strtok(line, " "); + for (unsigned j = 0; j < m_warp_size; j++) { + if (pch[0] == '1') + new_stack_entry.m_active_mask.set(j); + else + new_stack_entry.m_active_mask.reset(j); + pch = strtok(NULL, " "); + } - + new_stack_entry.m_pc = atoi(pch); + pch = strtok(NULL, " "); + new_stack_entry.m_calldepth = atoi(pch); + pch = strtok(NULL, " "); + new_stack_entry.m_recvg_pc = atoi(pch); + pch = strtok(NULL, " "); + new_stack_entry.m_branch_div_cycle = atoi(pch); + pch = strtok(NULL, " "); + if (pch[0] == '0') + new_stack_entry.m_type = STACK_ENTRY_TYPE_NORMAL; + else + new_stack_entry.m_type = STACK_ENTRY_TYPE_CALL; + m_stack.push_back(new_stack_entry); + } + fclose(fp2); } -const simt_mask_t &simt_stack::get_active_mask() const -{ - assert(m_stack.size() > 0); - return m_stack.back().m_active_mask; +const simt_mask_t &simt_stack::get_active_mask() const { + assert(m_stack.size() > 0); + return m_stack.back().m_active_mask; } -void simt_stack::get_pdom_stack_top_info( unsigned *pc, unsigned *rpc ) const -{ - assert(m_stack.size() > 0); - *pc = m_stack.back().m_pc; - *rpc = m_stack.back().m_recvg_pc; +void simt_stack::get_pdom_stack_top_info(unsigned *pc, unsigned *rpc) const { + assert(m_stack.size() > 0); + *pc = m_stack.back().m_pc; + *rpc = m_stack.back().m_recvg_pc; } -unsigned simt_stack::get_rp() const -{ - assert(m_stack.size() > 0); - return m_stack.back().m_recvg_pc; +unsigned simt_stack::get_rp() const { + assert(m_stack.size() > 0); + return m_stack.back().m_recvg_pc; } -void simt_stack::print (FILE *fout) const -{ - for ( unsigned k=0; k < m_stack.size(); k++ ) { - simt_stack_entry stack_entry = m_stack[k]; - if ( k==0 ) { - fprintf(fout, "w%02d %1u ", m_warp_id, k ); - } else { - fprintf(fout, " %1u ", k ); - } - for (unsigned j=0; j<m_warp_size; j++) - fprintf(fout, "%c", (stack_entry.m_active_mask.test(j)?'1':'0') ); - fprintf(fout, " pc: 0x%03x", stack_entry.m_pc ); - if ( stack_entry.m_recvg_pc == (unsigned)-1 ) { - fprintf(fout," rp: ---- tp: %s cd: %2u ", (stack_entry.m_type==STACK_ENTRY_TYPE_CALL?"C":"N"), stack_entry.m_calldepth ); - } else { - fprintf(fout," rp: %4u tp: %s cd: %2u ", stack_entry.m_recvg_pc, (stack_entry.m_type==STACK_ENTRY_TYPE_CALL?"C":"N"), stack_entry.m_calldepth ); - } - if ( stack_entry.m_branch_div_cycle != 0 ) { - fprintf(fout," bd@%6u ", (unsigned) stack_entry.m_branch_div_cycle ); - } else { - fprintf(fout," " ); - } - m_gpu->gpgpu_ctx->func_sim->ptx_print_insn( stack_entry.m_pc, fout ); - fprintf(fout,"\n"); +void simt_stack::print(FILE *fout) const { + for (unsigned k = 0; k < m_stack.size(); k++) { + simt_stack_entry stack_entry = m_stack[k]; + if (k == 0) { + fprintf(fout, "w%02d %1u ", m_warp_id, k); + } else { + fprintf(fout, " %1u ", k); } - -} - -void simt_stack::print_checkpoint (FILE *fout) const -{ - for ( unsigned k=0; k < m_stack.size(); k++ ) { - simt_stack_entry stack_entry = m_stack[k]; - - for (unsigned j=0; j<m_warp_size; j++) - fprintf(fout, "%c ", (stack_entry.m_active_mask.test(j)?'1':'0') ); - fprintf(fout, "%d %d %d %lld %d ", stack_entry.m_pc,stack_entry.m_calldepth,stack_entry.m_recvg_pc,stack_entry.m_branch_div_cycle,stack_entry.m_type ); - fprintf(fout, "%d %d\n",m_warp_id, m_warp_size ); - + for (unsigned j = 0; j < m_warp_size; j++) + fprintf(fout, "%c", (stack_entry.m_active_mask.test(j) ? '1' : '0')); + fprintf(fout, " pc: 0x%03x", stack_entry.m_pc); + if (stack_entry.m_recvg_pc == (unsigned)-1) { + fprintf(fout, " rp: ---- tp: %s cd: %2u ", + (stack_entry.m_type == STACK_ENTRY_TYPE_CALL ? "C" : "N"), + stack_entry.m_calldepth); + } else { + fprintf(fout, " rp: %4u tp: %s cd: %2u ", stack_entry.m_recvg_pc, + (stack_entry.m_type == STACK_ENTRY_TYPE_CALL ? "C" : "N"), + stack_entry.m_calldepth); + } + if (stack_entry.m_branch_div_cycle != 0) { + fprintf(fout, " bd@%6u ", (unsigned)stack_entry.m_branch_div_cycle); + } else { + fprintf(fout, " "); } + m_gpu->gpgpu_ctx->func_sim->ptx_print_insn(stack_entry.m_pc, fout); + fprintf(fout, "\n"); + } } -void simt_stack::update( simt_mask_t &thread_done, addr_vector_t &next_pc, address_type recvg_pc, op_type next_inst_op,unsigned next_inst_size, address_type next_inst_pc ) -{ - assert(m_stack.size() > 0); +void simt_stack::print_checkpoint(FILE *fout) const { + for (unsigned k = 0; k < m_stack.size(); k++) { + simt_stack_entry stack_entry = m_stack[k]; - assert( next_pc.size() == m_warp_size ); + for (unsigned j = 0; j < m_warp_size; j++) + fprintf(fout, "%c ", (stack_entry.m_active_mask.test(j) ? '1' : '0')); + fprintf(fout, "%d %d %d %lld %d ", stack_entry.m_pc, + stack_entry.m_calldepth, stack_entry.m_recvg_pc, + stack_entry.m_branch_div_cycle, stack_entry.m_type); + fprintf(fout, "%d %d\n", m_warp_id, m_warp_size); + } +} - simt_mask_t top_active_mask = m_stack.back().m_active_mask; - address_type top_recvg_pc = m_stack.back().m_recvg_pc; - address_type top_pc = m_stack.back().m_pc; // the pc of the instruction just executed - stack_entry_type top_type = m_stack.back().m_type; - assert(top_pc==next_inst_pc); - assert(top_active_mask.any()); +void simt_stack::update(simt_mask_t &thread_done, addr_vector_t &next_pc, + address_type recvg_pc, op_type next_inst_op, + unsigned next_inst_size, address_type next_inst_pc) { + assert(m_stack.size() > 0); - const address_type null_pc = -1; - bool warp_diverged = false; - address_type new_recvg_pc = null_pc; - unsigned num_divergent_paths=0; + assert(next_pc.size() == m_warp_size); - std::map<address_type,simt_mask_t> divergent_paths; - while (top_active_mask.any()) { + simt_mask_t top_active_mask = m_stack.back().m_active_mask; + address_type top_recvg_pc = m_stack.back().m_recvg_pc; + address_type top_pc = + m_stack.back().m_pc; // the pc of the instruction just executed + stack_entry_type top_type = m_stack.back().m_type; + assert(top_pc == next_inst_pc); + 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; - 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); - } - } - } + const address_type null_pc = -1; + bool warp_diverged = false; + address_type new_recvg_pc = null_pc; + unsigned num_divergent_paths = 0; - if(tmp_next_pc == null_pc) { - assert(!top_active_mask.any()); // all threads done - continue; + std::map<address_type, simt_mask_t> divergent_paths; + while (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; + 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); } - - divergent_paths[tmp_next_pc]=tmp_active_mask; - num_divergent_paths++; + } } + if (tmp_next_pc == null_pc) { + assert(!top_active_mask.any()); // all threads done + continue; + } - address_type not_taken_pc = next_inst_pc+next_inst_size; - assert(num_divergent_paths<=2); - for(unsigned i=0; i<num_divergent_paths; i++){ - address_type tmp_next_pc = null_pc; - simt_mask_t tmp_active_mask; - tmp_active_mask.reset(); - if(divergent_paths.find(not_taken_pc)!=divergent_paths.end()){ - assert(i==0); - tmp_next_pc=not_taken_pc; - tmp_active_mask=divergent_paths[tmp_next_pc]; - divergent_paths.erase(tmp_next_pc); - }else{ - std::map<address_type,simt_mask_t>:: iterator it=divergent_paths.begin(); - tmp_next_pc=it->first; - tmp_active_mask=divergent_paths[tmp_next_pc]; - divergent_paths.erase(tmp_next_pc); - } - - // HANDLE THE SPECIAL CASES FIRST - if (next_inst_op== CALL_OPS){ - // Since call is not a divergent instruction, all threads should have executed a call instruction - assert(num_divergent_paths == 1); - - simt_stack_entry new_stack_entry; - new_stack_entry.m_pc = tmp_next_pc; - new_stack_entry.m_active_mask = tmp_active_mask; - new_stack_entry.m_branch_div_cycle = m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle; - new_stack_entry.m_type = STACK_ENTRY_TYPE_CALL; - m_stack.push_back(new_stack_entry); - return; - }else if(next_inst_op == RET_OPS && top_type==STACK_ENTRY_TYPE_CALL){ - // pop the CALL Entry - assert(num_divergent_paths == 1); - m_stack.pop_back(); + divergent_paths[tmp_next_pc] = tmp_active_mask; + num_divergent_paths++; + } - assert(m_stack.size() > 0); - m_stack.back().m_pc=tmp_next_pc;// set the PC of the stack top entry to return PC from the call stack; - // Check if the New top of the stack is reconverging - if (tmp_next_pc == m_stack.back().m_recvg_pc && m_stack.back().m_type!=STACK_ENTRY_TYPE_CALL){ - assert(m_stack.back().m_type==STACK_ENTRY_TYPE_NORMAL); - m_stack.pop_back(); - } - return; - } + address_type not_taken_pc = next_inst_pc + next_inst_size; + assert(num_divergent_paths <= 2); + for (unsigned i = 0; i < num_divergent_paths; i++) { + address_type tmp_next_pc = null_pc; + simt_mask_t tmp_active_mask; + tmp_active_mask.reset(); + if (divergent_paths.find(not_taken_pc) != divergent_paths.end()) { + assert(i == 0); + tmp_next_pc = not_taken_pc; + tmp_active_mask = divergent_paths[tmp_next_pc]; + divergent_paths.erase(tmp_next_pc); + } else { + std::map<address_type, simt_mask_t>::iterator it = + divergent_paths.begin(); + tmp_next_pc = it->first; + tmp_active_mask = divergent_paths[tmp_next_pc]; + divergent_paths.erase(tmp_next_pc); + } - // discard the new entry if its PC matches with reconvergence PC - // that automatically reconverges the entry - // If the top stack entry is CALL, dont reconverge. - if (tmp_next_pc == top_recvg_pc && (top_type != STACK_ENTRY_TYPE_CALL)) continue; + // HANDLE THE SPECIAL CASES FIRST + if (next_inst_op == CALL_OPS) { + // Since call is not a divergent instruction, all threads should have + // executed a call instruction + assert(num_divergent_paths == 1); - // this new entry is not converging - // if this entry does not include thread from the warp, divergence occurs - if ((num_divergent_paths>1) && !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_stack.back().m_pc = new_recvg_pc; - m_stack.back().m_branch_div_cycle = m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle; + simt_stack_entry new_stack_entry; + new_stack_entry.m_pc = tmp_next_pc; + new_stack_entry.m_active_mask = tmp_active_mask; + new_stack_entry.m_branch_div_cycle = + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle; + new_stack_entry.m_type = STACK_ENTRY_TYPE_CALL; + m_stack.push_back(new_stack_entry); + return; + } else if (next_inst_op == RET_OPS && top_type == STACK_ENTRY_TYPE_CALL) { + // pop the CALL Entry + assert(num_divergent_paths == 1); + m_stack.pop_back(); - m_stack.push_back(simt_stack_entry()); - } - } + assert(m_stack.size() > 0); + m_stack.back().m_pc = tmp_next_pc; // set the PC of the stack top entry + // to return PC from the call stack; + // Check if the New top of the stack is reconverging + if (tmp_next_pc == m_stack.back().m_recvg_pc && + m_stack.back().m_type != STACK_ENTRY_TYPE_CALL) { + assert(m_stack.back().m_type == STACK_ENTRY_TYPE_NORMAL); + m_stack.pop_back(); + } + return; + } - // discard the new entry if its PC matches with reconvergence PC - if (warp_diverged && tmp_next_pc == new_recvg_pc) continue; + // discard the new entry if its PC matches with reconvergence PC + // that automatically reconverges the entry + // If the top stack entry is CALL, dont reconverge. + if (tmp_next_pc == top_recvg_pc && (top_type != STACK_ENTRY_TYPE_CALL)) + continue; - // update the current top of pdom stack - m_stack.back().m_pc = tmp_next_pc; - m_stack.back().m_active_mask = tmp_active_mask; - if (warp_diverged) { - m_stack.back().m_calldepth = 0; - m_stack.back().m_recvg_pc = new_recvg_pc; - } else { - m_stack.back().m_recvg_pc = top_recvg_pc; - } + // this new entry is not converging + // if this entry does not include thread from the warp, divergence occurs + if ((num_divergent_paths > 1) && !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_stack.back().m_pc = new_recvg_pc; + m_stack.back().m_branch_div_cycle = + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle; m_stack.push_back(simt_stack_entry()); + } } - assert(m_stack.size() > 0); - m_stack.pop_back(); + // discard the new entry if its PC matches with reconvergence PC + if (warp_diverged && tmp_next_pc == new_recvg_pc) continue; + // update the current top of pdom stack + m_stack.back().m_pc = tmp_next_pc; + m_stack.back().m_active_mask = tmp_active_mask; if (warp_diverged) { - m_gpu->gpgpu_ctx->stats->ptx_file_line_stats_add_warp_divergence(top_pc, 1); + m_stack.back().m_calldepth = 0; + m_stack.back().m_recvg_pc = new_recvg_pc; + } else { + m_stack.back().m_recvg_pc = top_recvg_pc; } + + m_stack.push_back(simt_stack_entry()); + } + assert(m_stack.size() > 0); + m_stack.pop_back(); + + if (warp_diverged) { + m_gpu->gpgpu_ctx->stats->ptx_file_line_stats_add_warp_divergence(top_pc, 1); + } } -void core_t::execute_warp_inst_t(warp_inst_t &inst, unsigned warpId) -{ - for ( unsigned t=0; t < m_warp_size; t++ ) { - if( inst.active(t) ) { - if(warpId==(unsigned (-1))) - warpId = inst.warp_id(); - unsigned tid=m_warp_size*warpId+t; - m_thread[tid]->ptx_exec_inst(inst,t); - - //virtual function - checkExecutionStatusAndUpdate(inst,t,tid); - } - } +void core_t::execute_warp_inst_t(warp_inst_t &inst, unsigned warpId) { + for (unsigned t = 0; t < m_warp_size; t++) { + if (inst.active(t)) { + if (warpId == (unsigned(-1))) warpId = inst.warp_id(); + unsigned tid = m_warp_size * warpId + t; + m_thread[tid]->ptx_exec_inst(inst, t); + + // virtual function + checkExecutionStatusAndUpdate(inst, t, tid); + } + } } - -bool core_t::ptx_thread_done( unsigned hw_thread_id ) const -{ - return ((m_thread[ hw_thread_id ]==NULL) || m_thread[ hw_thread_id ]->is_done()); + +bool core_t::ptx_thread_done(unsigned hw_thread_id) const { + return ((m_thread[hw_thread_id] == NULL) || + m_thread[hw_thread_id]->is_done()); } - -void core_t::updateSIMTStack(unsigned warpId, warp_inst_t * inst) -{ - simt_mask_t thread_done; - addr_vector_t next_pc; - unsigned wtid = warpId * m_warp_size; - for (unsigned i = 0; i < m_warp_size; i++) { - if( ptx_thread_done(wtid+i) ) { - thread_done.set(i); - next_pc.push_back( (address_type)-1 ); - } else { - if( inst->reconvergence_pc == RECONVERGE_RETURN_PC ) - inst->reconvergence_pc = get_return_pc(m_thread[wtid+i]); - next_pc.push_back( m_thread[wtid+i]->get_pc() ); - } + +void core_t::updateSIMTStack(unsigned warpId, warp_inst_t *inst) { + simt_mask_t thread_done; + addr_vector_t next_pc; + unsigned wtid = warpId * m_warp_size; + for (unsigned i = 0; i < m_warp_size; i++) { + if (ptx_thread_done(wtid + i)) { + thread_done.set(i); + next_pc.push_back((address_type)-1); + } else { + if (inst->reconvergence_pc == RECONVERGE_RETURN_PC) + inst->reconvergence_pc = get_return_pc(m_thread[wtid + i]); + next_pc.push_back(m_thread[wtid + i]->get_pc()); } - m_simt_stack[warpId]->update(thread_done,next_pc,inst->reconvergence_pc, inst->op,inst->isize,inst->pc); + } + m_simt_stack[warpId]->update(thread_done, next_pc, inst->reconvergence_pc, + inst->op, inst->isize, inst->pc); } //! Get the warp to be executed using the data taken form the SIMT stack -warp_inst_t core_t::getExecuteWarp(unsigned warpId) -{ - unsigned pc,rpc; - m_simt_stack[warpId]->get_pdom_stack_top_info(&pc,&rpc); - warp_inst_t wi= *(m_gpu->gpgpu_ctx->ptx_fetch_inst(pc)); - wi.set_active(m_simt_stack[warpId]->get_active_mask()); - return wi; +warp_inst_t core_t::getExecuteWarp(unsigned warpId) { + unsigned pc, rpc; + m_simt_stack[warpId]->get_pdom_stack_top_info(&pc, &rpc); + warp_inst_t wi = *(m_gpu->gpgpu_ctx->ptx_fetch_inst(pc)); + wi.set_active(m_simt_stack[warpId]->get_active_mask()); + return wi; } -void core_t::deleteSIMTStack() -{ - if ( m_simt_stack ) { - for (unsigned i = 0; i < m_warp_count; ++i) - delete m_simt_stack[i]; - delete[] m_simt_stack; - m_simt_stack = NULL; - } +void core_t::deleteSIMTStack() { + if (m_simt_stack) { + for (unsigned i = 0; i < m_warp_count; ++i) delete m_simt_stack[i]; + delete[] m_simt_stack; + m_simt_stack = NULL; + } } -void core_t::initilizeSIMTStack(unsigned warp_count, unsigned warp_size) -{ - m_simt_stack = new simt_stack*[warp_count]; - for (unsigned i = 0; i < warp_count; ++i) - m_simt_stack[i] = new simt_stack(i,warp_size,m_gpu); - m_warp_size = warp_size; - m_warp_count = warp_count; +void core_t::initilizeSIMTStack(unsigned warp_count, unsigned warp_size) { + m_simt_stack = new simt_stack *[warp_count]; + for (unsigned i = 0; i < warp_count; ++i) + m_simt_stack[i] = new simt_stack(i, warp_size, m_gpu); + m_warp_size = warp_size; + m_warp_count = warp_count; } -void core_t::get_pdom_stack_top_info( unsigned warpId, unsigned *pc, unsigned *rpc ) const -{ - m_simt_stack[warpId]->get_pdom_stack_top_info(pc,rpc); +void core_t::get_pdom_stack_top_info(unsigned warpId, unsigned *pc, + unsigned *rpc) const { + m_simt_stack[warpId]->get_pdom_stack_top_info(pc, rpc); } diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 29e4a30..206ae06 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -7,14 +7,16 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this +// Redistributions in binary form must reproduce the above copyright notice, +// this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -33,45 +35,41 @@ class gpgpu_sim; class kernel_info_t; class gpgpu_context; - -//Set a hard limit of 32 CTAs per shader [cuda only has 8] +// Set a hard limit of 32 CTAs per shader [cuda only has 8] #define MAX_CTA_PER_SHADER 32 #define MAX_BARRIERS_PER_CTA 16 -//After expanding the vector input and output operands +// After expanding the vector input and output operands #define MAX_INPUT_VALUES 24 #define MAX_OUTPUT_VALUES 8 enum _memory_space_t { - undefined_space=0, - reg_space, - local_space, - shared_space, - sstarr_space, - param_space_unclassified, - param_space_kernel, /* global to all threads in a kernel : read-only */ - param_space_local, /* local to a thread : read-writable */ - const_space, - tex_space, - surf_space, - global_space, - generic_space, - instruction_space + undefined_space = 0, + reg_space, + local_space, + shared_space, + sstarr_space, + param_space_unclassified, + param_space_kernel, /* global to all threads in a kernel : read-only */ + param_space_local, /* local to a thread : read-writable */ + const_space, + tex_space, + surf_space, + global_space, + generic_space, + instruction_space }; - -enum FuncCache -{ +enum FuncCache { FuncCachePreferNone = 0, FuncCachePreferShared = 1, FuncCachePreferL1 = 2 }; - #ifdef __cplusplus -#include <string.h> #include <stdio.h> +#include <string.h> #include <set> typedef unsigned long long new_addr_type; @@ -79,371 +77,357 @@ typedef unsigned long long cudaTextureObject_t; typedef unsigned address_type; typedef unsigned addr_t; -// the following are operations the timing model can see +// the following are operations the timing model can see enum uarch_op_t { - NO_OP=-1, - ALU_OP=1, - SFU_OP, - TENSOR_CORE_OP, - DP_OP, - SP_OP, - INTP_OP, - ALU_SFU_OP, - LOAD_OP, - TENSOR_CORE_LOAD_OP, - TENSOR_CORE_STORE_OP, - STORE_OP, - BRANCH_OP, - BARRIER_OP, - MEMORY_BARRIER_OP, - CALL_OPS, - RET_OPS + NO_OP = -1, + ALU_OP = 1, + SFU_OP, + TENSOR_CORE_OP, + DP_OP, + SP_OP, + INTP_OP, + ALU_SFU_OP, + LOAD_OP, + TENSOR_CORE_LOAD_OP, + TENSOR_CORE_STORE_OP, + STORE_OP, + BRANCH_OP, + BARRIER_OP, + MEMORY_BARRIER_OP, + CALL_OPS, + RET_OPS }; typedef enum uarch_op_t op_type; - -enum uarch_bar_t { - NOT_BAR=-1, - SYNC=1, - ARRIVE, - RED -}; +enum uarch_bar_t { NOT_BAR = -1, SYNC = 1, ARRIVE, RED }; typedef enum uarch_bar_t barrier_type; -enum uarch_red_t { - NOT_RED=-1, - POPC_RED=1, - AND_RED, - OR_RED -}; +enum uarch_red_t { NOT_RED = -1, POPC_RED = 1, AND_RED, OR_RED }; typedef enum uarch_red_t reduction_type; - -enum uarch_operand_type_t { - UN_OP=-1, - INT_OP, - FP_OP -}; +enum uarch_operand_type_t { UN_OP = -1, INT_OP, FP_OP }; typedef enum uarch_operand_type_t types_of_operands; enum special_operations_t { - OTHER_OP, - INT__OP, - INT_MUL24_OP, - INT_MUL32_OP, - INT_MUL_OP, - INT_DIV_OP, - FP_MUL_OP, - FP_DIV_OP, - FP__OP, - FP_SQRT_OP, - FP_LG_OP, - FP_SIN_OP, - FP_EXP_OP + OTHER_OP, + INT__OP, + INT_MUL24_OP, + INT_MUL32_OP, + INT_MUL_OP, + INT_DIV_OP, + FP_MUL_OP, + FP_DIV_OP, + FP__OP, + FP_SQRT_OP, + FP_LG_OP, + FP_SIN_OP, + FP_EXP_OP }; -typedef enum special_operations_t special_ops; // Required to identify for the power model +typedef enum special_operations_t + special_ops; // Required to identify for the power model enum operation_pipeline_t { - UNKOWN_OP, - SP__OP, - DP__OP, - INTP__OP, - SFU__OP, - TENSOR_CORE__OP, - MEM__OP + UNKOWN_OP, + SP__OP, + DP__OP, + INTP__OP, + SFU__OP, + TENSOR_CORE__OP, + MEM__OP }; typedef enum operation_pipeline_t operation_pipeline; -enum mem_operation_t { - NOT_TEX, - TEX -}; +enum mem_operation_t { NOT_TEX, TEX }; typedef enum mem_operation_t mem_operation; -enum _memory_op_t { - no_memory_op = 0, - memory_load, - memory_store -}; +enum _memory_op_t { no_memory_op = 0, memory_load, memory_store }; -#include <bitset> -#include <list> -#include <vector> #include <assert.h> #include <stdlib.h> -#include <map> -#include <deque> #include <algorithm> +#include <bitset> +#include <deque> +#include <list> +#include <map> +#include <vector> #if !defined(__VECTOR_TYPES_H__) #include "vector_types.h" #endif struct dim3comp { - bool operator() (const dim3 & a, const dim3 & b) const - { - if(a.z < b.z) - return true; - else if(a.y < b.y) - return true; - else if (a.x < b.x) - return true; - else - return false; - } + bool operator()(const dim3 &a, const dim3 &b) const { + if (a.z < b.z) + return true; + else if (a.y < b.y) + return true; + else if (a.x < b.x) + return true; + else + return false; + } }; -void increment_x_then_y_then_z( dim3 &i, const dim3 &bound); +void increment_x_then_y_then_z(dim3 &i, const dim3 &bound); -//Jin: child kernel information for CDP +// Jin: child kernel information for CDP #include "stream_manager.h" class stream_manager; struct CUstream_st; -//extern stream_manager * g_stream_manager; -//support for pinned memories added -extern std::map<void *,void **> pinned_memory; +// extern stream_manager * g_stream_manager; +// support for pinned memories added +extern std::map<void *, void **> pinned_memory; extern std::map<void *, size_t> pinned_memory_size; class kernel_info_t { -public: -// kernel_info_t() -// { -// m_valid=false; -// m_kernel_entry=NULL; -// m_uid=0; -// m_num_cores_running=0; -// m_param_mem=NULL; -// } - kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry); - kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map<std::string, const struct cudaArray*> nameToCudaArray, std::map<std::string, const struct textureInfo*> nameToTextureInfo); - ~kernel_info_t(); + public: + // kernel_info_t() + // { + // m_valid=false; + // m_kernel_entry=NULL; + // m_uid=0; + // m_num_cores_running=0; + // m_param_mem=NULL; + // } + kernel_info_t(dim3 gridDim, dim3 blockDim, class function_info *entry); + kernel_info_t( + dim3 gridDim, dim3 blockDim, class function_info *entry, + std::map<std::string, const struct cudaArray *> nameToCudaArray, + std::map<std::string, const struct textureInfo *> nameToTextureInfo); + ~kernel_info_t(); - void inc_running() { m_num_cores_running++; } - void dec_running() - { - assert( m_num_cores_running > 0 ); - m_num_cores_running--; - } - bool running() const { return m_num_cores_running>0; } - bool done() const - { - return no_more_ctas_to_run() && !running(); - } - class function_info *entry() { return m_kernel_entry; } - const class function_info *entry() const { return m_kernel_entry; } + void inc_running() { m_num_cores_running++; } + void dec_running() { + assert(m_num_cores_running > 0); + m_num_cores_running--; + } + bool running() const { return m_num_cores_running > 0; } + bool done() const { return no_more_ctas_to_run() && !running(); } + class function_info *entry() { + return m_kernel_entry; + } + const class function_info *entry() const { return m_kernel_entry; } - size_t num_blocks() const - { - return m_grid_dim.x * m_grid_dim.y * m_grid_dim.z; - } + size_t num_blocks() const { + return m_grid_dim.x * m_grid_dim.y * m_grid_dim.z; + } - size_t threads_per_cta() const - { - return m_block_dim.x * m_block_dim.y * m_block_dim.z; - } + size_t threads_per_cta() const { + return m_block_dim.x * m_block_dim.y * m_block_dim.z; + } - dim3 get_grid_dim() const { return m_grid_dim; } - dim3 get_cta_dim() const { return m_block_dim; } + dim3 get_grid_dim() const { return m_grid_dim; } + dim3 get_cta_dim() const { return m_block_dim; } - void increment_cta_id() - { - increment_x_then_y_then_z(m_next_cta,m_grid_dim); - m_next_tid.x=0; - m_next_tid.y=0; - m_next_tid.z=0; - } - dim3 get_next_cta_id() const { return m_next_cta; } - unsigned get_next_cta_id_single() const - { - return m_next_cta.x + m_grid_dim.x*m_next_cta.y + m_grid_dim.x*m_grid_dim.y*m_next_cta.z; - } - bool no_more_ctas_to_run() const - { - return (m_next_cta.x >= m_grid_dim.x || m_next_cta.y >= m_grid_dim.y || m_next_cta.z >= m_grid_dim.z ); - } + void increment_cta_id() { + increment_x_then_y_then_z(m_next_cta, m_grid_dim); + m_next_tid.x = 0; + m_next_tid.y = 0; + m_next_tid.z = 0; + } + dim3 get_next_cta_id() const { return m_next_cta; } + unsigned get_next_cta_id_single() const { + return m_next_cta.x + m_grid_dim.x * m_next_cta.y + + m_grid_dim.x * m_grid_dim.y * m_next_cta.z; + } + bool no_more_ctas_to_run() const { + return (m_next_cta.x >= m_grid_dim.x || m_next_cta.y >= m_grid_dim.y || + m_next_cta.z >= m_grid_dim.z); + } + + void increment_thread_id() { + increment_x_then_y_then_z(m_next_tid, m_block_dim); + } + dim3 get_next_thread_id_3d() const { return m_next_tid; } + unsigned get_next_thread_id() const { + return m_next_tid.x + m_block_dim.x * m_next_tid.y + + m_block_dim.x * m_block_dim.y * m_next_tid.z; + } + bool more_threads_in_cta() const { + return m_next_tid.z < m_block_dim.z && m_next_tid.y < m_block_dim.y && + m_next_tid.x < m_block_dim.x; + } + unsigned get_uid() const { return m_uid; } + std::string name() const; + + std::list<class ptx_thread_info *> &active_threads() { + return m_active_threads; + } + class memory_space *get_param_memory() { + return m_param_mem; + } - void increment_thread_id() { increment_x_then_y_then_z(m_next_tid,m_block_dim); } - dim3 get_next_thread_id_3d() const { return m_next_tid; } - unsigned get_next_thread_id() const - { - return m_next_tid.x + m_block_dim.x*m_next_tid.y + m_block_dim.x*m_block_dim.y*m_next_tid.z; - } - bool more_threads_in_cta() const - { - return m_next_tid.z < m_block_dim.z && m_next_tid.y < m_block_dim.y && m_next_tid.x < m_block_dim.x; - } - unsigned get_uid() const { return m_uid; } - std::string name() const; + // The following functions access texture bindings present at the kernel's + // launch - std::list<class ptx_thread_info *> &active_threads() { return m_active_threads; } - class memory_space *get_param_memory() { return m_param_mem; } + const struct cudaArray *get_texarray(const std::string &texname) const { + std::map<std::string, const struct cudaArray *>::const_iterator t = + m_NameToCudaArray.find(texname); + assert(t != m_NameToCudaArray.end()); + return t->second; + } - - //The following functions access texture bindings present at the kernel's launch - - const struct cudaArray* get_texarray( const std::string &texname ) const - { - std::map<std::string,const struct cudaArray*>::const_iterator t=m_NameToCudaArray.find(texname); - assert(t != m_NameToCudaArray.end()); - return t->second; - } + const struct textureInfo *get_texinfo(const std::string &texname) const { + std::map<std::string, const struct textureInfo *>::const_iterator t = + m_NameToTextureInfo.find(texname); + assert(t != m_NameToTextureInfo.end()); + return t->second; + } - const struct textureInfo* get_texinfo( const std::string &texname ) const - { - std::map<std::string, const struct textureInfo*>::const_iterator t=m_NameToTextureInfo.find(texname); - assert(t != m_NameToTextureInfo.end()); - return t->second; - } + private: + kernel_info_t(const kernel_info_t &); // disable copy constructor + void operator=(const kernel_info_t &); // disable copy operator -private: - kernel_info_t( const kernel_info_t & ); // disable copy constructor - void operator=( const kernel_info_t & ); // disable copy operator + class function_info *m_kernel_entry; - class function_info *m_kernel_entry; + unsigned m_uid; - unsigned m_uid; - - //These maps contain the snapshot of the texture mappings at kernel launch - std::map<std::string, const struct cudaArray*> m_NameToCudaArray; - std::map<std::string, const struct textureInfo*> m_NameToTextureInfo; + // These maps contain the snapshot of the texture mappings at kernel launch + std::map<std::string, const struct cudaArray *> m_NameToCudaArray; + std::map<std::string, const struct textureInfo *> m_NameToTextureInfo; - dim3 m_grid_dim; - dim3 m_block_dim; - dim3 m_next_cta; - dim3 m_next_tid; + dim3 m_grid_dim; + dim3 m_block_dim; + dim3 m_next_cta; + dim3 m_next_tid; - unsigned m_num_cores_running; + unsigned m_num_cores_running; - std::list<class ptx_thread_info *> m_active_threads; - class memory_space *m_param_mem; + std::list<class ptx_thread_info *> m_active_threads; + class memory_space *m_param_mem; -public: - //Jin: parent and child kernel management for CDP - void set_parent(kernel_info_t * parent, dim3 parent_ctaid, dim3 parent_tid); - void set_child(kernel_info_t * child); - void remove_child(kernel_info_t * child); - bool is_finished(); - bool children_all_finished(); - void notify_parent_finished(); - CUstream_st * create_stream_cta(dim3 ctaid); - CUstream_st * get_default_stream_cta(dim3 ctaid); - bool cta_has_stream(dim3 ctaid, CUstream_st* stream); - void destroy_cta_streams(); - void print_parent_info(); - kernel_info_t * get_parent() { return m_parent_kernel; } + public: + // Jin: parent and child kernel management for CDP + void set_parent(kernel_info_t *parent, dim3 parent_ctaid, dim3 parent_tid); + void set_child(kernel_info_t *child); + void remove_child(kernel_info_t *child); + bool is_finished(); + bool children_all_finished(); + void notify_parent_finished(); + CUstream_st *create_stream_cta(dim3 ctaid); + CUstream_st *get_default_stream_cta(dim3 ctaid); + bool cta_has_stream(dim3 ctaid, CUstream_st *stream); + void destroy_cta_streams(); + void print_parent_info(); + kernel_info_t *get_parent() { return m_parent_kernel; } -private: - kernel_info_t * m_parent_kernel; - dim3 m_parent_ctaid; - dim3 m_parent_tid; - std::list<kernel_info_t *> m_child_kernels; //child kernel launched - std::map< dim3, std::list<CUstream_st *>, dim3comp > m_cta_streams; //streams created in each CTA + private: + kernel_info_t *m_parent_kernel; + dim3 m_parent_ctaid; + dim3 m_parent_tid; + std::list<kernel_info_t *> m_child_kernels; // child kernel launched + std::map<dim3, std::list<CUstream_st *>, dim3comp> + m_cta_streams; // streams created in each CTA -//Jin: kernel timing -public: - unsigned long long launch_cycle; - unsigned long long start_cycle; - unsigned long long end_cycle; - unsigned m_launch_latency; + // Jin: kernel timing + public: + unsigned long long launch_cycle; + unsigned long long start_cycle; + unsigned long long end_cycle; + unsigned m_launch_latency; - mutable bool volta_cache_config_set; + mutable bool volta_cache_config_set; }; class core_config { - public: - core_config(gpgpu_context* ctx) - { - gpgpu_ctx = ctx; - m_valid = false; - num_shmem_bank=16; - shmem_limited_broadcast = false; - gpgpu_shmem_sizeDefault=(unsigned)-1; - gpgpu_shmem_sizePrefL1=(unsigned)-1; - gpgpu_shmem_sizePrefShared=(unsigned)-1; - } - virtual void init() = 0; + public: + core_config(gpgpu_context *ctx) { + gpgpu_ctx = ctx; + m_valid = false; + num_shmem_bank = 16; + shmem_limited_broadcast = false; + gpgpu_shmem_sizeDefault = (unsigned)-1; + gpgpu_shmem_sizePrefL1 = (unsigned)-1; + gpgpu_shmem_sizePrefShared = (unsigned)-1; + } + virtual void init() = 0; - bool m_valid; - unsigned warp_size; - // backward pointer - class gpgpu_context* gpgpu_ctx; + bool m_valid; + unsigned warp_size; + // backward pointer + class gpgpu_context *gpgpu_ctx; - // off-chip memory request architecture parameters - int gpgpu_coalesce_arch; + // off-chip memory request architecture parameters + int gpgpu_coalesce_arch; - // shared memory bank conflict checking parameters - bool shmem_limited_broadcast; - static const address_type WORD_SIZE=4; - unsigned num_shmem_bank; - unsigned shmem_bank_func(address_type addr) const - { - return ((addr/WORD_SIZE) % num_shmem_bank); - } - unsigned mem_warp_parts; - mutable unsigned gpgpu_shmem_size; - unsigned gpgpu_shmem_sizeDefault; - unsigned gpgpu_shmem_sizePrefL1; - unsigned gpgpu_shmem_sizePrefShared; - unsigned mem_unit_ports; + // shared memory bank conflict checking parameters + bool shmem_limited_broadcast; + static const address_type WORD_SIZE = 4; + unsigned num_shmem_bank; + unsigned shmem_bank_func(address_type addr) const { + return ((addr / WORD_SIZE) % num_shmem_bank); + } + unsigned mem_warp_parts; + mutable unsigned gpgpu_shmem_size; + unsigned gpgpu_shmem_sizeDefault; + unsigned gpgpu_shmem_sizePrefL1; + unsigned gpgpu_shmem_sizePrefShared; + unsigned mem_unit_ports; - // texture and constant cache line sizes (used to determine number of memory accesses) - unsigned gpgpu_cache_texl1_linesize; - unsigned gpgpu_cache_constl1_linesize; + // texture and constant cache line sizes (used to determine number of memory + // accesses) + unsigned gpgpu_cache_texl1_linesize; + unsigned gpgpu_cache_constl1_linesize; - unsigned gpgpu_max_insn_issue_per_warp; - bool gmem_skip_L1D; // on = global memory access always skip the L1 cache + unsigned gpgpu_max_insn_issue_per_warp; + bool gmem_skip_L1D; // on = global memory access always skip the L1 cache - bool adaptive_volta_cache_config; + bool adaptive_volta_cache_config; }; -// bounded stack that implements simt reconvergence using pdom mechanism from MICRO'07 paper +// bounded stack that implements simt reconvergence using pdom mechanism from +// MICRO'07 paper const unsigned MAX_WARP_SIZE = 32; typedef std::bitset<MAX_WARP_SIZE> active_mask_t; -#define MAX_WARP_SIZE_SIMT_STACK MAX_WARP_SIZE +#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: - simt_stack( unsigned wid, unsigned warpSize, class gpgpu_sim * gpu); - - void reset(); - void launch( address_type start_pc, const simt_mask_t &active_mask ); - void update( simt_mask_t &thread_done, addr_vector_t &next_pc, address_type recvg_pc, op_type next_inst_op,unsigned next_inst_size, address_type next_inst_pc ); + public: + simt_stack(unsigned wid, unsigned warpSize, class gpgpu_sim *gpu); - const simt_mask_t &get_active_mask() const; - void get_pdom_stack_top_info( unsigned *pc, unsigned *rpc ) const; - unsigned get_rp() const; - void print(FILE *fp) const; - void resume(char * fname) ; - void print_checkpoint (FILE *fout) const; + void reset(); + void launch(address_type start_pc, const simt_mask_t &active_mask); + void update(simt_mask_t &thread_done, addr_vector_t &next_pc, + address_type recvg_pc, op_type next_inst_op, + unsigned next_inst_size, address_type next_inst_pc); -protected: - unsigned m_warp_id; - unsigned m_warp_size; + const simt_mask_t &get_active_mask() const; + void get_pdom_stack_top_info(unsigned *pc, unsigned *rpc) const; + unsigned get_rp() const; + void print(FILE *fp) const; + void resume(char *fname); + void print_checkpoint(FILE *fout) const; + protected: + unsigned m_warp_id; + unsigned m_warp_size; - enum stack_entry_type { - STACK_ENTRY_TYPE_NORMAL = 0, - STACK_ENTRY_TYPE_CALL - }; + enum stack_entry_type { STACK_ENTRY_TYPE_NORMAL = 0, STACK_ENTRY_TYPE_CALL }; - struct simt_stack_entry { - address_type m_pc; - unsigned int m_calldepth; - simt_mask_t m_active_mask; - address_type m_recvg_pc; - unsigned long long m_branch_div_cycle; - stack_entry_type m_type; - simt_stack_entry() : - m_pc(-1), m_calldepth(0), m_active_mask(), m_recvg_pc(-1), m_branch_div_cycle(0), m_type(STACK_ENTRY_TYPE_NORMAL) { }; - }; + struct simt_stack_entry { + address_type m_pc; + unsigned int m_calldepth; + simt_mask_t m_active_mask; + address_type m_recvg_pc; + unsigned long long m_branch_div_cycle; + stack_entry_type m_type; + simt_stack_entry() + : m_pc(-1), + m_calldepth(0), + m_active_mask(), + m_recvg_pc(-1), + m_branch_div_cycle(0), + m_type(STACK_ENTRY_TYPE_NORMAL){}; + }; - std::deque<simt_stack_entry> m_stack; + std::deque<simt_stack_entry> m_stack; - class gpgpu_sim * m_gpu; + class gpgpu_sim *m_gpu; }; // Let's just upgrade to C++11 so we can use constexpr here... -// start allocating from this address (lower values used for allocating globals in .ptx file) +// start allocating from this address (lower values used for allocating globals +// in .ptx file) const unsigned long long GLOBAL_HEAP_START = 0xC0000000; // Volta max shmem size is 96kB const unsigned long long SHARED_MEM_SIZE_MAX = 96 * (1 << 10); @@ -455,873 +439,931 @@ const unsigned MAX_STREAMING_MULTIPROCESSORS = 80; const unsigned MAX_THREAD_PER_SM = 1 << 11; // MAX 64 warps / SM const unsigned MAX_WARP_PER_SM = 1 << 6; -const unsigned long long TOTAL_LOCAL_MEM_PER_SM = MAX_THREAD_PER_SM * LOCAL_MEM_SIZE_MAX; -const unsigned long long TOTAL_SHARED_MEM = MAX_STREAMING_MULTIPROCESSORS * SHARED_MEM_SIZE_MAX; -const unsigned long long TOTAL_LOCAL_MEM = MAX_STREAMING_MULTIPROCESSORS * MAX_THREAD_PER_SM * LOCAL_MEM_SIZE_MAX; -const unsigned long long SHARED_GENERIC_START = GLOBAL_HEAP_START - TOTAL_SHARED_MEM; -const unsigned long long LOCAL_GENERIC_START = SHARED_GENERIC_START - TOTAL_LOCAL_MEM; -const unsigned long long STATIC_ALLOC_LIMIT = GLOBAL_HEAP_START - (TOTAL_LOCAL_MEM + TOTAL_SHARED_MEM); +const unsigned long long TOTAL_LOCAL_MEM_PER_SM = + MAX_THREAD_PER_SM * LOCAL_MEM_SIZE_MAX; +const unsigned long long TOTAL_SHARED_MEM = + MAX_STREAMING_MULTIPROCESSORS * SHARED_MEM_SIZE_MAX; +const unsigned long long TOTAL_LOCAL_MEM = + MAX_STREAMING_MULTIPROCESSORS * MAX_THREAD_PER_SM * LOCAL_MEM_SIZE_MAX; +const unsigned long long SHARED_GENERIC_START = + GLOBAL_HEAP_START - TOTAL_SHARED_MEM; +const unsigned long long LOCAL_GENERIC_START = + SHARED_GENERIC_START - TOTAL_LOCAL_MEM; +const unsigned long long STATIC_ALLOC_LIMIT = + GLOBAL_HEAP_START - (TOTAL_LOCAL_MEM + TOTAL_SHARED_MEM); #if !defined(__CUDA_RUNTIME_API_H__) #include "builtin_types.h" struct cudaArray { - void *devPtr; - int devPtr32; - struct cudaChannelFormatDesc desc; - int width; - int height; - int size; //in bytes - unsigned dimensions; + void *devPtr; + int devPtr32; + struct cudaChannelFormatDesc desc; + int width; + int height; + int size; // in bytes + unsigned dimensions; }; #endif -// Struct that record other attributes in the textureReference declaration +// Struct that record other attributes in the textureReference declaration // - These attributes are passed thru __cudaRegisterTexture() struct textureReferenceAttr { - const struct textureReference *m_texref; - int m_dim; - enum cudaTextureReadMode m_readmode; - int m_ext; - textureReferenceAttr(const struct textureReference *texref, - int dim, - enum cudaTextureReadMode readmode, - int ext) - : m_texref(texref), m_dim(dim), m_readmode(readmode), m_ext(ext) - { } + const struct textureReference *m_texref; + int m_dim; + enum cudaTextureReadMode m_readmode; + int m_ext; + textureReferenceAttr(const struct textureReference *texref, int dim, + enum cudaTextureReadMode readmode, int ext) + : m_texref(texref), m_dim(dim), m_readmode(readmode), m_ext(ext) {} }; -class gpgpu_functional_sim_config -{ -public: - void reg_options(class OptionParser * opp); +class gpgpu_functional_sim_config { + public: + void reg_options(class OptionParser *opp); - void ptx_set_tex_cache_linesize(unsigned linesize); + void ptx_set_tex_cache_linesize(unsigned linesize); - unsigned get_forced_max_capability() const { return m_ptx_force_max_capability; } - bool convert_to_ptxplus() const { return m_ptx_convert_to_ptxplus; } - bool use_cuobjdump() const { return m_ptx_use_cuobjdump; } - bool experimental_lib_support() const { return m_experimental_lib_support; } + unsigned get_forced_max_capability() const { + return m_ptx_force_max_capability; + } + bool convert_to_ptxplus() const { return m_ptx_convert_to_ptxplus; } + bool use_cuobjdump() const { return m_ptx_use_cuobjdump; } + bool experimental_lib_support() const { return m_experimental_lib_support; } - int get_ptx_inst_debug_to_file() const { return g_ptx_inst_debug_to_file; } - const char* get_ptx_inst_debug_file() const { return g_ptx_inst_debug_file; } - int get_ptx_inst_debug_thread_uid() const { return g_ptx_inst_debug_thread_uid; } - unsigned get_texcache_linesize() const { return m_texcache_linesize; } - int get_checkpoint_option() const {return checkpoint_option; } - int get_checkpoint_kernel() const {return checkpoint_kernel; } - int get_checkpoint_CTA() const {return checkpoint_CTA; } - int get_resume_option() const {return resume_option; } - int get_resume_kernel() const {return resume_kernel; } - int get_resume_CTA() const {return resume_CTA; } - int get_checkpoint_CTA_t() const {return checkpoint_CTA_t; } - int get_checkpoint_insn_Y() const {return checkpoint_insn_Y; } -private: - // PTX options - int m_ptx_convert_to_ptxplus; - int m_ptx_use_cuobjdump; - int m_experimental_lib_support; - unsigned m_ptx_force_max_capability; - int checkpoint_option; - int checkpoint_kernel; - int checkpoint_CTA; - unsigned resume_option; - unsigned resume_kernel; - unsigned resume_CTA; - unsigned checkpoint_CTA_t; - int checkpoint_insn_Y; - int g_ptx_inst_debug_to_file; - char* g_ptx_inst_debug_file; - int g_ptx_inst_debug_thread_uid; + int get_ptx_inst_debug_to_file() const { return g_ptx_inst_debug_to_file; } + const char *get_ptx_inst_debug_file() const { return g_ptx_inst_debug_file; } + int get_ptx_inst_debug_thread_uid() const { + return g_ptx_inst_debug_thread_uid; + } + unsigned get_texcache_linesize() const { return m_texcache_linesize; } + int get_checkpoint_option() const { return checkpoint_option; } + int get_checkpoint_kernel() const { return checkpoint_kernel; } + int get_checkpoint_CTA() const { return checkpoint_CTA; } + int get_resume_option() const { return resume_option; } + int get_resume_kernel() const { return resume_kernel; } + int get_resume_CTA() const { return resume_CTA; } + int get_checkpoint_CTA_t() const { return checkpoint_CTA_t; } + int get_checkpoint_insn_Y() const { return checkpoint_insn_Y; } - unsigned m_texcache_linesize; -}; + private: + // PTX options + int m_ptx_convert_to_ptxplus; + int m_ptx_use_cuobjdump; + int m_experimental_lib_support; + unsigned m_ptx_force_max_capability; + int checkpoint_option; + int checkpoint_kernel; + int checkpoint_CTA; + unsigned resume_option; + unsigned resume_kernel; + unsigned resume_CTA; + unsigned checkpoint_CTA_t; + int checkpoint_insn_Y; + int g_ptx_inst_debug_to_file; + char *g_ptx_inst_debug_file; + int g_ptx_inst_debug_thread_uid; + unsigned m_texcache_linesize; +}; class gpgpu_t { -public: - gpgpu_t( const gpgpu_functional_sim_config &config, gpgpu_context* ctx ); - // backward pointer - class gpgpu_context* gpgpu_ctx; - int checkpoint_option; - int checkpoint_kernel; - int checkpoint_CTA; - unsigned resume_option; - unsigned resume_kernel; - unsigned resume_CTA; - unsigned checkpoint_CTA_t; - int checkpoint_insn_Y; + public: + gpgpu_t(const gpgpu_functional_sim_config &config, gpgpu_context *ctx); + // backward pointer + class gpgpu_context *gpgpu_ctx; + int checkpoint_option; + int checkpoint_kernel; + int checkpoint_CTA; + unsigned resume_option; + unsigned resume_kernel; + unsigned resume_CTA; + unsigned checkpoint_CTA_t; + int checkpoint_insn_Y; - //Move some cycle core stats here instead of being global - unsigned long long gpu_sim_cycle; - unsigned long long gpu_tot_sim_cycle; + // Move some cycle core stats here instead of being global + unsigned long long gpu_sim_cycle; + unsigned long long gpu_tot_sim_cycle; + void *gpu_malloc(size_t size); + void *gpu_mallocarray(size_t count); + void gpu_memset(size_t dst_start_addr, int c, size_t count); + void memcpy_to_gpu(size_t dst_start_addr, const void *src, size_t count); + void memcpy_from_gpu(void *dst, size_t src_start_addr, size_t count); + void memcpy_gpu_to_gpu(size_t dst, size_t src, size_t count); - void* gpu_malloc( size_t size ); - void* gpu_mallocarray( size_t count ); - void gpu_memset( size_t dst_start_addr, int c, size_t count ); - void memcpy_to_gpu( size_t dst_start_addr, const void *src, size_t count ); - void memcpy_from_gpu( void *dst, size_t src_start_addr, size_t count ); - void memcpy_gpu_to_gpu( size_t dst, size_t src, size_t count ); - - class memory_space *get_global_memory() { return m_global_mem; } - class memory_space *get_tex_memory() { return m_tex_mem; } - class memory_space *get_surf_memory() { return m_surf_mem; } + class memory_space *get_global_memory() { + return m_global_mem; + } + class memory_space *get_tex_memory() { + return m_tex_mem; + } + class memory_space *get_surf_memory() { + return m_surf_mem; + } - void gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* texref, const struct cudaArray* array); - void gpgpu_ptx_sim_bindNameToTexture(const char* name, const struct textureReference* texref, int dim, int readmode, int ext); - void gpgpu_ptx_sim_unbindTexture(const struct textureReference* texref); - const char* gpgpu_ptx_sim_findNamefromTexture(const struct textureReference* texref); + void gpgpu_ptx_sim_bindTextureToArray(const struct textureReference *texref, + const struct cudaArray *array); + void gpgpu_ptx_sim_bindNameToTexture(const char *name, + const struct textureReference *texref, + int dim, int readmode, int ext); + void gpgpu_ptx_sim_unbindTexture(const struct textureReference *texref); + const char *gpgpu_ptx_sim_findNamefromTexture( + const struct textureReference *texref); - const struct textureReference* get_texref( const std::string &texname ) const - { - std::map<std::string, std::set<const struct textureReference*> >::const_iterator t=m_NameToTextureRef.find(texname); - assert( t != m_NameToTextureRef.end() ); - return *(t->second.begin()); - } + const struct textureReference *get_texref(const std::string &texname) const { + std::map<std::string, + std::set<const struct textureReference *> >::const_iterator t = + m_NameToTextureRef.find(texname); + assert(t != m_NameToTextureRef.end()); + return *(t->second.begin()); + } - const struct cudaArray* get_texarray( const std::string &texname ) const - { - std::map<std::string,const struct cudaArray*>::const_iterator t=m_NameToCudaArray.find(texname); - assert(t != m_NameToCudaArray.end()); - return t->second; - } + const struct cudaArray *get_texarray(const std::string &texname) const { + std::map<std::string, const struct cudaArray *>::const_iterator t = + m_NameToCudaArray.find(texname); + assert(t != m_NameToCudaArray.end()); + return t->second; + } - const struct textureInfo* get_texinfo( const std::string &texname ) const - { - std::map<std::string, const struct textureInfo*>::const_iterator t=m_NameToTextureInfo.find(texname); - assert(t != m_NameToTextureInfo.end()); - return t->second; - } + const struct textureInfo *get_texinfo(const std::string &texname) const { + std::map<std::string, const struct textureInfo *>::const_iterator t = + m_NameToTextureInfo.find(texname); + assert(t != m_NameToTextureInfo.end()); + return t->second; + } - const struct textureReferenceAttr* get_texattr( const std::string &texname ) const - { - std::map<std::string, const struct textureReferenceAttr*>::const_iterator t=m_NameToAttribute.find(texname); - assert(t != m_NameToAttribute.end()); - return t->second; - } + const struct textureReferenceAttr *get_texattr( + const std::string &texname) const { + std::map<std::string, const struct textureReferenceAttr *>::const_iterator + t = m_NameToAttribute.find(texname); + assert(t != m_NameToAttribute.end()); + return t->second; + } - const gpgpu_functional_sim_config &get_config() const { return m_function_model_config; } - FILE* get_ptx_inst_debug_file() { return ptx_inst_debug_file; } - - // These maps return the current texture mappings for the GPU at any given time. - std::map<std::string, const struct cudaArray*> getNameArrayMapping() {return m_NameToCudaArray;} - std::map<std::string, const struct textureInfo*> getNameInfoMapping() {return m_NameToTextureInfo;} + const gpgpu_functional_sim_config &get_config() const { + return m_function_model_config; + } + FILE *get_ptx_inst_debug_file() { return ptx_inst_debug_file; } -protected: - const gpgpu_functional_sim_config &m_function_model_config; - FILE* ptx_inst_debug_file; + // These maps return the current texture mappings for the GPU at any given + // time. + std::map<std::string, const struct cudaArray *> getNameArrayMapping() { + return m_NameToCudaArray; + } + std::map<std::string, const struct textureInfo *> getNameInfoMapping() { + return m_NameToTextureInfo; + } - class memory_space *m_global_mem; - class memory_space *m_tex_mem; - class memory_space *m_surf_mem; + protected: + const gpgpu_functional_sim_config &m_function_model_config; + FILE *ptx_inst_debug_file; - unsigned long long m_dev_malloc; - // These maps contain the current texture mappings for the GPU at any given time. - std::map<std::string, std::set<const struct textureReference*> > m_NameToTextureRef; - std::map<const struct textureReference*, std::string> m_TextureRefToName; - std::map<std::string, const struct cudaArray*> m_NameToCudaArray; - std::map<std::string, const struct textureInfo*> m_NameToTextureInfo; - std::map<std::string, const struct textureReferenceAttr*> m_NameToAttribute; -}; + class memory_space *m_global_mem; + class memory_space *m_tex_mem; + class memory_space *m_surf_mem; -struct gpgpu_ptx_sim_info -{ - // Holds properties of the kernel (Kernel's resource use). - // These will be set to zero if a ptxinfo file is not present. - int lmem; - int smem; - int cmem; - int gmem; - int regs; - unsigned maxthreads; - unsigned ptx_version; - unsigned sm_target; + unsigned long long m_dev_malloc; + // These maps contain the current texture mappings for the GPU at any given + // time. + std::map<std::string, std::set<const struct textureReference *> > + m_NameToTextureRef; + std::map<const struct textureReference *, std::string> m_TextureRefToName; + std::map<std::string, const struct cudaArray *> m_NameToCudaArray; + std::map<std::string, const struct textureInfo *> m_NameToTextureInfo; + std::map<std::string, const struct textureReferenceAttr *> m_NameToAttribute; }; +struct gpgpu_ptx_sim_info { + // Holds properties of the kernel (Kernel's resource use). + // These will be set to zero if a ptxinfo file is not present. + int lmem; + int smem; + int cmem; + int gmem; + int regs; + unsigned maxthreads; + unsigned ptx_version; + unsigned sm_target; +}; struct gpgpu_ptx_sim_arg { - gpgpu_ptx_sim_arg() { m_start=NULL; } - gpgpu_ptx_sim_arg(const void *arg, size_t size, size_t offset) - { - m_start=arg; - m_nbytes=size; - m_offset=offset; - } - const void *m_start; - size_t m_nbytes; - size_t m_offset; + gpgpu_ptx_sim_arg() { m_start = NULL; } + gpgpu_ptx_sim_arg(const void *arg, size_t size, size_t offset) { + m_start = arg; + m_nbytes = size; + m_offset = offset; + } + const void *m_start; + size_t m_nbytes; + size_t m_offset; }; typedef std::list<gpgpu_ptx_sim_arg> gpgpu_ptx_sim_arg_list_t; class memory_space_t { -public: - memory_space_t() { m_type = undefined_space; m_bank=0; } - memory_space_t( const enum _memory_space_t &from ) { m_type = from; m_bank = 0; } - bool operator==( const memory_space_t &x ) const { return (m_bank == x.m_bank) && (m_type == x.m_type); } - bool operator!=( const memory_space_t &x ) const { return !(*this == x); } - bool operator<( const memory_space_t &x ) const - { - if(m_type < x.m_type) - return true; - else if(m_type > x.m_type) - return false; - else if( m_bank < x.m_bank ) - return true; + public: + memory_space_t() { + m_type = undefined_space; + m_bank = 0; + } + memory_space_t(const enum _memory_space_t &from) { + m_type = from; + m_bank = 0; + } + bool operator==(const memory_space_t &x) const { + return (m_bank == x.m_bank) && (m_type == x.m_type); + } + bool operator!=(const memory_space_t &x) const { return !(*this == x); } + bool operator<(const memory_space_t &x) const { + if (m_type < x.m_type) + return true; + else if (m_type > x.m_type) return false; - } - enum _memory_space_t get_type() const { return m_type; } - void set_type( enum _memory_space_t t ) { m_type = t; } - unsigned get_bank() const { return m_bank; } - void set_bank( unsigned b ) { m_bank = b; } - bool is_const() const { return (m_type == const_space) || (m_type == param_space_kernel); } - bool is_local() const { return (m_type == local_space) || (m_type == param_space_local); } - bool is_global() const { return (m_type == global_space); } + else if (m_bank < x.m_bank) + return true; + return false; + } + enum _memory_space_t get_type() const { return m_type; } + void set_type(enum _memory_space_t t) { m_type = t; } + unsigned get_bank() const { return m_bank; } + void set_bank(unsigned b) { m_bank = b; } + bool is_const() const { + return (m_type == const_space) || (m_type == param_space_kernel); + } + bool is_local() const { + return (m_type == local_space) || (m_type == param_space_local); + } + bool is_global() const { return (m_type == global_space); } -private: - enum _memory_space_t m_type; - unsigned m_bank; // n in ".const[n]"; note .const == .const[0] (see PTX 2.1 manual, sec. 5.1.3) + private: + enum _memory_space_t m_type; + unsigned m_bank; // n in ".const[n]"; note .const == .const[0] (see PTX 2.1 + // manual, sec. 5.1.3) }; const unsigned MAX_MEMORY_ACCESS_SIZE = 128; typedef std::bitset<MAX_MEMORY_ACCESS_SIZE> mem_access_byte_mask_t; -const unsigned SECTOR_CHUNCK_SIZE = 4; //four sectors -const unsigned SECTOR_SIZE = 32 ; //sector is 32 bytes width +const unsigned SECTOR_CHUNCK_SIZE = 4; // four sectors +const unsigned SECTOR_SIZE = 32; // sector is 32 bytes width typedef std::bitset<SECTOR_CHUNCK_SIZE> mem_access_sector_mask_t; #define NO_PARTIAL_WRITE (mem_access_byte_mask_t()) -#define MEM_ACCESS_TYPE_TUP_DEF \ -MA_TUP_BEGIN( mem_access_type ) \ - MA_TUP( GLOBAL_ACC_R ), \ - MA_TUP( LOCAL_ACC_R ), \ - MA_TUP( CONST_ACC_R ), \ - MA_TUP( TEXTURE_ACC_R ), \ - MA_TUP( GLOBAL_ACC_W ), \ - MA_TUP( LOCAL_ACC_W ), \ - MA_TUP( L1_WRBK_ACC ), \ - MA_TUP( L2_WRBK_ACC ), \ - MA_TUP( INST_ACC_R ), \ - MA_TUP( L1_WR_ALLOC_R ), \ - MA_TUP( L2_WR_ALLOC_R ), \ - MA_TUP( NUM_MEM_ACCESS_TYPE ) \ -MA_TUP_END( mem_access_type ) +#define MEM_ACCESS_TYPE_TUP_DEF \ + MA_TUP_BEGIN(mem_access_type) \ + MA_TUP(GLOBAL_ACC_R) \ + , MA_TUP(LOCAL_ACC_R), MA_TUP(CONST_ACC_R), MA_TUP(TEXTURE_ACC_R), \ + MA_TUP(GLOBAL_ACC_W), MA_TUP(LOCAL_ACC_W), MA_TUP(L1_WRBK_ACC), \ + MA_TUP(L2_WRBK_ACC), MA_TUP(INST_ACC_R), MA_TUP(L1_WR_ALLOC_R), \ + MA_TUP(L2_WR_ALLOC_R), \ + MA_TUP(NUM_MEM_ACCESS_TYPE) MA_TUP_END(mem_access_type) #define MA_TUP_BEGIN(X) enum X { #define MA_TUP(X) X -#define MA_TUP_END(X) }; +#define MA_TUP_END(X) \ + } \ + ; MEM_ACCESS_TYPE_TUP_DEF #undef MA_TUP_BEGIN #undef MA_TUP #undef MA_TUP_END -const char * mem_access_type_str(enum mem_access_type access_type); +const char *mem_access_type_str(enum mem_access_type access_type); enum cache_operator_type { - CACHE_UNDEFINED, + CACHE_UNDEFINED, + + // loads + CACHE_ALL, // .ca + CACHE_LAST_USE, // .lu + CACHE_VOLATILE, // .cv + CACHE_L1, // .nc - // loads - CACHE_ALL, // .ca - CACHE_LAST_USE, // .lu - CACHE_VOLATILE, // .cv - CACHE_L1, // .nc - - // loads and stores - CACHE_STREAMING, // .cs - CACHE_GLOBAL, // .cg + // loads and stores + CACHE_STREAMING, // .cs + CACHE_GLOBAL, // .cg - // stores - CACHE_WRITE_BACK, // .wb - CACHE_WRITE_THROUGH // .wt + // stores + CACHE_WRITE_BACK, // .wb + CACHE_WRITE_THROUGH // .wt }; class mem_access_t { -public: - mem_access_t(gpgpu_context* ctx) { init(ctx); } - mem_access_t( mem_access_type type, - new_addr_type address, - unsigned size, - bool wr, - gpgpu_context* ctx) - { - init(ctx); - m_type = type; - m_addr = address; - m_req_size = size; - m_write = wr; - } - mem_access_t( mem_access_type type, - new_addr_type address, - unsigned size, - bool wr, - const active_mask_t &active_mask, - const mem_access_byte_mask_t &byte_mask, - const mem_access_sector_mask_t §or_mask, - gpgpu_context* ctx) - : m_warp_mask(active_mask), m_byte_mask(byte_mask), m_sector_mask(sector_mask) - { - init(ctx); - m_type = type; - m_addr = address; - m_req_size = size; - m_write = wr; - } + public: + mem_access_t(gpgpu_context *ctx) { init(ctx); } + mem_access_t(mem_access_type type, new_addr_type address, unsigned size, + bool wr, gpgpu_context *ctx) { + init(ctx); + m_type = type; + m_addr = address; + m_req_size = size; + m_write = wr; + } + mem_access_t(mem_access_type type, new_addr_type address, unsigned size, + bool wr, const active_mask_t &active_mask, + const mem_access_byte_mask_t &byte_mask, + const mem_access_sector_mask_t §or_mask, gpgpu_context *ctx) + : m_warp_mask(active_mask), + m_byte_mask(byte_mask), + m_sector_mask(sector_mask) { + init(ctx); + m_type = type; + m_addr = address; + m_req_size = size; + m_write = wr; + } - new_addr_type get_addr() const { return m_addr; } - void set_addr(new_addr_type addr) {m_addr=addr;} - unsigned get_size() const { return m_req_size; } - const active_mask_t &get_warp_mask() const { return m_warp_mask; } - bool is_write() const { return m_write; } - enum mem_access_type get_type() const { return m_type; } - mem_access_byte_mask_t get_byte_mask() const { return m_byte_mask; } - mem_access_sector_mask_t get_sector_mask() const { return m_sector_mask; } + new_addr_type get_addr() const { return m_addr; } + void set_addr(new_addr_type addr) { m_addr = addr; } + unsigned get_size() const { return m_req_size; } + const active_mask_t &get_warp_mask() const { return m_warp_mask; } + bool is_write() const { return m_write; } + enum mem_access_type get_type() const { return m_type; } + mem_access_byte_mask_t get_byte_mask() const { return m_byte_mask; } + mem_access_sector_mask_t get_sector_mask() const { return m_sector_mask; } - void print(FILE *fp) const - { - fprintf(fp,"addr=0x%llx, %s, size=%u, ", m_addr, m_write?"store":"load ", m_req_size ); - switch(m_type) { - case GLOBAL_ACC_R: fprintf(fp,"GLOBAL_R"); break; - case LOCAL_ACC_R: fprintf(fp,"LOCAL_R "); break; - case CONST_ACC_R: fprintf(fp,"CONST "); break; - case TEXTURE_ACC_R: fprintf(fp,"TEXTURE "); break; - case GLOBAL_ACC_W: fprintf(fp,"GLOBAL_W"); break; - case LOCAL_ACC_W: fprintf(fp,"LOCAL_W "); break; - case L2_WRBK_ACC: fprintf(fp,"L2_WRBK "); break; - case INST_ACC_R: fprintf(fp,"INST "); break; - case L1_WRBK_ACC: fprintf(fp,"L1_WRBK "); break; - default: fprintf(fp,"unknown "); break; - } - } + void print(FILE *fp) const { + fprintf(fp, "addr=0x%llx, %s, size=%u, ", m_addr, + m_write ? "store" : "load ", m_req_size); + switch (m_type) { + case GLOBAL_ACC_R: + fprintf(fp, "GLOBAL_R"); + break; + case LOCAL_ACC_R: + fprintf(fp, "LOCAL_R "); + break; + case CONST_ACC_R: + fprintf(fp, "CONST "); + break; + case TEXTURE_ACC_R: + fprintf(fp, "TEXTURE "); + break; + case GLOBAL_ACC_W: + fprintf(fp, "GLOBAL_W"); + break; + case LOCAL_ACC_W: + fprintf(fp, "LOCAL_W "); + break; + case L2_WRBK_ACC: + fprintf(fp, "L2_WRBK "); + break; + case INST_ACC_R: + fprintf(fp, "INST "); + break; + case L1_WRBK_ACC: + fprintf(fp, "L1_WRBK "); + break; + default: + fprintf(fp, "unknown "); + break; + } + } - gpgpu_context* gpgpu_ctx; -private: - void init(gpgpu_context* ctx); + gpgpu_context *gpgpu_ctx; - unsigned m_uid; - new_addr_type m_addr; // request address - bool m_write; - unsigned m_req_size; // bytes - mem_access_type m_type; - active_mask_t m_warp_mask; - mem_access_byte_mask_t m_byte_mask; - mem_access_sector_mask_t m_sector_mask; + private: + void init(gpgpu_context *ctx); + + unsigned m_uid; + new_addr_type m_addr; // request address + bool m_write; + unsigned m_req_size; // bytes + mem_access_type m_type; + active_mask_t m_warp_mask; + mem_access_byte_mask_t m_byte_mask; + mem_access_sector_mask_t m_sector_mask; }; class mem_fetch; class mem_fetch_interface { -public: - virtual bool full( unsigned size, bool write ) const = 0; - virtual void push( mem_fetch *mf ) = 0; + public: + virtual bool full(unsigned size, bool write) const = 0; + virtual void push(mem_fetch *mf) = 0; }; class mem_fetch_allocator { -public: - virtual mem_fetch *alloc( new_addr_type addr, mem_access_type type, unsigned size, bool wr, unsigned long long cycle ) const = 0; - virtual mem_fetch *alloc( const class warp_inst_t &inst, const mem_access_t &access, unsigned long long cycle ) const = 0; + public: + virtual mem_fetch *alloc(new_addr_type addr, mem_access_type type, + unsigned size, bool wr, + unsigned long long cycle) const = 0; + virtual mem_fetch *alloc(const class warp_inst_t &inst, + const mem_access_t &access, + unsigned long long cycle) const = 0; }; -// the maximum number of destination, source, or address uarch operands in a instruction -#define MAX_REG_OPERANDS 32 +// the maximum number of destination, source, or address uarch operands in a +// instruction +#define MAX_REG_OPERANDS 32 struct dram_callback_t { - dram_callback_t() { function=NULL; instruction=NULL; thread=NULL; } - void (*function)(const class inst_t*, class ptx_thread_info*); + dram_callback_t() { + function = NULL; + instruction = NULL; + thread = NULL; + } + void (*function)(const class inst_t *, class ptx_thread_info *); - const class inst_t* instruction; - class ptx_thread_info *thread; + const class inst_t *instruction; + class ptx_thread_info *thread; }; class inst_t { -public: - inst_t() - { - m_decoded=false; - pc=(address_type)-1; - reconvergence_pc=(address_type)-1; - op=NO_OP; - bar_type=NOT_BAR; - red_type=NOT_RED; - bar_id=(unsigned)-1; - bar_count=(unsigned)-1; - oprnd_type=UN_OP; - sp_op=OTHER_OP; - op_pipe=UNKOWN_OP; - mem_op=NOT_TEX; - num_operands=0; - num_regs=0; - memset(out, 0, sizeof(unsigned)); - memset(in, 0, sizeof(unsigned)); - is_vectorin=0; - is_vectorout=0; - space = memory_space_t(); - cache_op = CACHE_UNDEFINED; - latency = 1; - initiation_interval = 1; - for( unsigned i=0; i < MAX_REG_OPERANDS; i++ ) { - arch_reg.src[i] = -1; - arch_reg.dst[i] = -1; - } - isize=0; + public: + inst_t() { + m_decoded = false; + pc = (address_type)-1; + reconvergence_pc = (address_type)-1; + op = NO_OP; + bar_type = NOT_BAR; + red_type = NOT_RED; + bar_id = (unsigned)-1; + bar_count = (unsigned)-1; + oprnd_type = UN_OP; + sp_op = OTHER_OP; + op_pipe = UNKOWN_OP; + mem_op = NOT_TEX; + num_operands = 0; + num_regs = 0; + memset(out, 0, sizeof(unsigned)); + memset(in, 0, sizeof(unsigned)); + is_vectorin = 0; + is_vectorout = 0; + space = memory_space_t(); + cache_op = CACHE_UNDEFINED; + latency = 1; + initiation_interval = 1; + for (unsigned i = 0; i < MAX_REG_OPERANDS; i++) { + arch_reg.src[i] = -1; + arch_reg.dst[i] = -1; } - bool valid() const { return m_decoded; } - virtual void print_insn( FILE *fp ) const - { - fprintf(fp," [inst @ pc=0x%04x] ", pc ); - } - bool is_load() const { return (op == LOAD_OP ||op==TENSOR_CORE_LOAD_OP || memory_op == memory_load); } - bool is_store() const { return (op == STORE_OP ||op==TENSOR_CORE_STORE_OP || memory_op == memory_store); } - unsigned get_num_operands() const {return num_operands;} - unsigned get_num_regs() const {return num_regs;} - void set_num_regs(unsigned num) {num_regs=num;} - void set_num_operands(unsigned num) {num_operands=num;} - void set_bar_id(unsigned id) {bar_id=id;} - void set_bar_count(unsigned count) {bar_count=count;} + isize = 0; + } + bool valid() const { return m_decoded; } + virtual void print_insn(FILE *fp) const { + fprintf(fp, " [inst @ pc=0x%04x] ", pc); + } + bool is_load() const { + return (op == LOAD_OP || op == TENSOR_CORE_LOAD_OP || + memory_op == memory_load); + } + bool is_store() const { + return (op == STORE_OP || op == TENSOR_CORE_STORE_OP || + memory_op == memory_store); + } + unsigned get_num_operands() const { return num_operands; } + unsigned get_num_regs() const { return num_regs; } + void set_num_regs(unsigned num) { num_regs = num; } + void set_num_operands(unsigned num) { num_operands = num; } + void set_bar_id(unsigned id) { bar_id = id; } + void set_bar_count(unsigned count) { bar_count = count; } - address_type pc; // program counter address of instruction - unsigned isize; // size of instruction in bytes - op_type op; // opcode (uarch visible) + address_type pc; // program counter address of instruction + unsigned isize; // size of instruction in bytes + op_type op; // opcode (uarch visible) - barrier_type bar_type; - reduction_type red_type; - unsigned bar_id; - unsigned bar_count; + barrier_type bar_type; + reduction_type red_type; + unsigned bar_id; + unsigned bar_count; - types_of_operands oprnd_type; // code (uarch visible) identify if the operation is an interger or a floating point - special_ops sp_op; // code (uarch visible) identify if int_alu, fp_alu, int_mul .... - operation_pipeline op_pipe; // code (uarch visible) identify the pipeline of the operation (SP, SFU or MEM) - mem_operation mem_op; // code (uarch visible) identify memory type - _memory_op_t memory_op; // memory_op used by ptxplus - unsigned num_operands; - unsigned num_regs; // count vector operand as one register operand + types_of_operands oprnd_type; // code (uarch visible) identify if the + // operation is an interger or a floating point + special_ops + sp_op; // code (uarch visible) identify if int_alu, fp_alu, int_mul .... + operation_pipeline op_pipe; // code (uarch visible) identify the pipeline of + // the operation (SP, SFU or MEM) + mem_operation mem_op; // code (uarch visible) identify memory type + _memory_op_t memory_op; // memory_op used by ptxplus + unsigned num_operands; + unsigned num_regs; // count vector operand as one register operand - address_type reconvergence_pc; // -1 => not a branch, -2 => use function return address - - unsigned out[8]; - unsigned outcount; - unsigned in[24]; - unsigned incount; - unsigned char is_vectorin; - unsigned char is_vectorout; - int pred; // predicate register number - int ar1, ar2; - // register number for bank conflict evaluation - struct { - int dst[MAX_REG_OPERANDS]; - int src[MAX_REG_OPERANDS]; - } arch_reg; - //int arch_reg[MAX_REG_OPERANDS]; // register number for bank conflict evaluation - unsigned latency; // operation latency - unsigned initiation_interval; + address_type reconvergence_pc; // -1 => not a branch, -2 => use function + // return address - unsigned data_size; // what is the size of the word being operated on? - memory_space_t space; - cache_operator_type cache_op; + unsigned out[8]; + unsigned outcount; + unsigned in[24]; + unsigned incount; + unsigned char is_vectorin; + unsigned char is_vectorout; + int pred; // predicate register number + int ar1, ar2; + // register number for bank conflict evaluation + struct { + int dst[MAX_REG_OPERANDS]; + int src[MAX_REG_OPERANDS]; + } arch_reg; + // int arch_reg[MAX_REG_OPERANDS]; // register number for bank conflict + // evaluation + unsigned latency; // operation latency + unsigned initiation_interval; -protected: - bool m_decoded; - virtual void pre_decode() {} -}; + unsigned data_size; // what is the size of the word being operated on? + memory_space_t space; + cache_operator_type cache_op; -enum divergence_support_t { - POST_DOMINATOR = 1, - NUM_SIMD_MODEL + protected: + bool m_decoded; + virtual void pre_decode() {} }; +enum divergence_support_t { POST_DOMINATOR = 1, NUM_SIMD_MODEL }; + const unsigned MAX_ACCESSES_PER_INSN_PER_THREAD = 8; -class warp_inst_t: public inst_t { -public: - // constructors - warp_inst_t() - { - m_uid=0; - m_empty=true; - m_config=NULL; - } - warp_inst_t( const core_config *config ) - { - m_uid=0; - assert(config->warp_size<=MAX_WARP_SIZE); - m_config=config; - m_empty=true; - m_isatomic=false; - m_per_scalar_thread_valid=false; - m_mem_accesses_created=false; - m_cache_hit=false; - m_is_printf=false; - m_is_cdp = 0; - } - virtual ~warp_inst_t(){ - } +class warp_inst_t : public inst_t { + public: + // constructors + warp_inst_t() { + m_uid = 0; + m_empty = true; + m_config = NULL; + } + warp_inst_t(const core_config *config) { + m_uid = 0; + assert(config->warp_size <= MAX_WARP_SIZE); + m_config = config; + m_empty = true; + m_isatomic = false; + m_per_scalar_thread_valid = false; + m_mem_accesses_created = false; + m_cache_hit = false; + m_is_printf = false; + m_is_cdp = 0; + } + virtual ~warp_inst_t() {} - // modifiers - void broadcast_barrier_reduction( const active_mask_t& access_mask); - void do_atomic(bool forceDo=false); - void do_atomic( const active_mask_t& access_mask, bool forceDo=false ); - void clear() - { - m_empty=true; - } + // modifiers + void broadcast_barrier_reduction(const active_mask_t &access_mask); + void do_atomic(bool forceDo = false); + void do_atomic(const active_mask_t &access_mask, bool forceDo = false); + void clear() { m_empty = true; } - void issue( const active_mask_t &mask, unsigned warp_id, unsigned long long cycle, int dynamic_warp_id, int sch_id ); + void issue(const active_mask_t &mask, unsigned warp_id, + unsigned long long cycle, int dynamic_warp_id, int sch_id); - const active_mask_t & get_active_mask() const - { - return m_warp_active_mask; - } - void completed( unsigned long long cycle ) const; // stat collection: called when the instruction is completed + const active_mask_t &get_active_mask() const { return m_warp_active_mask; } + void completed(unsigned long long cycle) + const; // stat collection: called when the instruction is completed - void set_addr( unsigned n, new_addr_type addr ) - { - if( !m_per_scalar_thread_valid ) { - m_per_scalar_thread.resize(m_config->warp_size); - m_per_scalar_thread_valid=true; - } - m_per_scalar_thread[n].memreqaddr[0] = addr; + void set_addr(unsigned n, new_addr_type addr) { + if (!m_per_scalar_thread_valid) { + m_per_scalar_thread.resize(m_config->warp_size); + m_per_scalar_thread_valid = true; } - void set_addr( unsigned n, new_addr_type* addr, unsigned num_addrs ) - { - if( !m_per_scalar_thread_valid ) { - m_per_scalar_thread.resize(m_config->warp_size); - m_per_scalar_thread_valid=true; - } - assert(num_addrs <= MAX_ACCESSES_PER_INSN_PER_THREAD); - for(unsigned i=0; i<num_addrs; i++) - m_per_scalar_thread[n].memreqaddr[i] = addr[i]; + m_per_scalar_thread[n].memreqaddr[0] = addr; + } + void set_addr(unsigned n, new_addr_type *addr, unsigned num_addrs) { + if (!m_per_scalar_thread_valid) { + m_per_scalar_thread.resize(m_config->warp_size); + m_per_scalar_thread_valid = true; } - void print_m_accessq(){ - - if(accessq_empty()) - return; - else{ - printf("Printing mem access generated\n"); - std::list<mem_access_t>::iterator it; - for (it = m_accessq.begin(); it != m_accessq.end(); ++it){ - printf("MEM_TXN_GEN:%s:%llx, Size:%d \n",mem_access_type_str(it->get_type()), it->get_addr(),it->get_size()); - } - } - } - struct transaction_info { - std::bitset<4> chunks; // bitmask: 32-byte chunks accessed - mem_access_byte_mask_t bytes; - active_mask_t active; // threads in this transaction - - bool test_bytes(unsigned start_bit, unsigned end_bit) { - for( unsigned i=start_bit; i<=end_bit; i++ ) - if(bytes.test(i)) - return true; - return false; - } - }; - - void generate_mem_accesses(); - void memory_coalescing_arch( bool is_write, mem_access_type access_type ); - void memory_coalescing_arch_atomic( bool is_write, mem_access_type access_type ); - void memory_coalescing_arch_reduce_and_send( bool is_write, mem_access_type access_type, const transaction_info &info, new_addr_type addr, unsigned segment_size ); - - void add_callback( unsigned lane_id, - void (*function)(const class inst_t*, class ptx_thread_info*), - const inst_t *inst, - class ptx_thread_info *thread, - bool atomic) - { - if( !m_per_scalar_thread_valid ) { - m_per_scalar_thread.resize(m_config->warp_size); - m_per_scalar_thread_valid=true; - if(atomic) m_isatomic=true; - } - m_per_scalar_thread[lane_id].callback.function = function; - m_per_scalar_thread[lane_id].callback.instruction = inst; - m_per_scalar_thread[lane_id].callback.thread = thread; + assert(num_addrs <= MAX_ACCESSES_PER_INSN_PER_THREAD); + for (unsigned i = 0; i < num_addrs; i++) + m_per_scalar_thread[n].memreqaddr[i] = addr[i]; + } + void print_m_accessq() { + if (accessq_empty()) + return; + else { + printf("Printing mem access generated\n"); + std::list<mem_access_t>::iterator it; + for (it = m_accessq.begin(); it != m_accessq.end(); ++it) { + printf("MEM_TXN_GEN:%s:%llx, Size:%d \n", + mem_access_type_str(it->get_type()), it->get_addr(), + it->get_size()); + } } - void set_active( const active_mask_t &active ); - - void clear_active( const active_mask_t &inactive ); - void set_not_active( unsigned lane_id ); + } + struct transaction_info { + std::bitset<4> chunks; // bitmask: 32-byte chunks accessed + mem_access_byte_mask_t bytes; + active_mask_t active; // threads in this transaction - // accessors - virtual void print_insn(FILE *fp) const - { - fprintf(fp," [inst @ pc=0x%04x] ", pc ); - for (int i=(int)m_config->warp_size-1; i>=0; i--) - fprintf(fp, "%c", ((m_warp_active_mask[i])?'1':'0') ); - } - bool active( unsigned thread ) const { return m_warp_active_mask.test(thread); } - unsigned active_count() const { return m_warp_active_mask.count(); } - unsigned issued_count() const { assert(m_empty == false); return m_warp_issued_mask.count(); } // for instruction counting - bool empty() const { return m_empty; } - unsigned warp_id() const - { - assert( !m_empty ); - return m_warp_id; - } - unsigned warp_id_func() const // to be used in functional simulations only - { - return m_warp_id; - } - unsigned dynamic_warp_id() const - { - assert( !m_empty ); - return m_dynamic_warp_id; - } - bool has_callback( unsigned n ) const - { - return m_warp_active_mask[n] && m_per_scalar_thread_valid && - (m_per_scalar_thread[n].callback.function!=NULL); - } - new_addr_type get_addr( unsigned n ) const - { - assert( m_per_scalar_thread_valid ); - return m_per_scalar_thread[n].memreqaddr[0]; + bool test_bytes(unsigned start_bit, unsigned end_bit) { + for (unsigned i = start_bit; i <= end_bit; i++) + if (bytes.test(i)) return true; + return false; } + }; - bool isatomic() const { return m_isatomic; } - - unsigned warp_size() const { return m_config->warp_size; } - - bool accessq_empty() const { return m_accessq.empty(); } - unsigned accessq_count() const { return m_accessq.size(); } - const mem_access_t &accessq_back() { return m_accessq.back(); } - void accessq_pop_back() { m_accessq.pop_back(); } + void generate_mem_accesses(); + void memory_coalescing_arch(bool is_write, mem_access_type access_type); + void memory_coalescing_arch_atomic(bool is_write, + mem_access_type access_type); + void memory_coalescing_arch_reduce_and_send(bool is_write, + mem_access_type access_type, + const transaction_info &info, + new_addr_type addr, + unsigned segment_size); - bool dispatch_delay() - { - if( cycles > 0 ) - cycles--; - return cycles > 0; + void add_callback(unsigned lane_id, void (*function)(const class inst_t *, + class ptx_thread_info *), + const inst_t *inst, class ptx_thread_info *thread, + bool atomic) { + if (!m_per_scalar_thread_valid) { + m_per_scalar_thread.resize(m_config->warp_size); + m_per_scalar_thread_valid = true; + if (atomic) m_isatomic = true; } + m_per_scalar_thread[lane_id].callback.function = function; + m_per_scalar_thread[lane_id].callback.instruction = inst; + m_per_scalar_thread[lane_id].callback.thread = thread; + } + void set_active(const active_mask_t &active); - bool has_dispatch_delay(){ - return cycles > 0; - } + void clear_active(const active_mask_t &inactive); + void set_not_active(unsigned lane_id); - void print( FILE *fout ) const; - unsigned get_uid() const { return m_uid; } - unsigned get_schd_id() const { return m_scheduler_id; } + // accessors + virtual void print_insn(FILE *fp) const { + fprintf(fp, " [inst @ pc=0x%04x] ", pc); + for (int i = (int)m_config->warp_size - 1; i >= 0; i--) + fprintf(fp, "%c", ((m_warp_active_mask[i]) ? '1' : '0')); + } + bool active(unsigned thread) const { return m_warp_active_mask.test(thread); } + unsigned active_count() const { return m_warp_active_mask.count(); } + unsigned issued_count() const { + assert(m_empty == false); + return m_warp_issued_mask.count(); + } // for instruction counting + bool empty() const { return m_empty; } + unsigned warp_id() const { + assert(!m_empty); + return m_warp_id; + } + unsigned warp_id_func() const // to be used in functional simulations only + { + return m_warp_id; + } + unsigned dynamic_warp_id() const { + assert(!m_empty); + return m_dynamic_warp_id; + } + bool has_callback(unsigned n) const { + return m_warp_active_mask[n] && m_per_scalar_thread_valid && + (m_per_scalar_thread[n].callback.function != NULL); + } + new_addr_type get_addr(unsigned n) const { + assert(m_per_scalar_thread_valid); + return m_per_scalar_thread[n].memreqaddr[0]; + } -protected: + bool isatomic() const { return m_isatomic; } - unsigned m_uid; - bool m_empty; - bool m_cache_hit; - unsigned long long issue_cycle; - unsigned cycles; // used for implementing initiation interval delay - bool m_isatomic; - bool m_is_printf; - unsigned m_warp_id; - unsigned m_dynamic_warp_id; - const core_config *m_config; - active_mask_t m_warp_active_mask; // dynamic active mask for timing model (after predication) - active_mask_t m_warp_issued_mask; // active mask at issue (prior to predication test) -- for instruction counting + unsigned warp_size() const { return m_config->warp_size; } - struct per_thread_info { - per_thread_info() { - for(unsigned i=0; i<MAX_ACCESSES_PER_INSN_PER_THREAD; i++) - memreqaddr[i] = 0; - } - dram_callback_t callback; - new_addr_type memreqaddr[MAX_ACCESSES_PER_INSN_PER_THREAD]; // effective address, upto 8 different requests (to support 32B access in 8 chunks of 4B each) - }; - bool m_per_scalar_thread_valid; - std::vector<per_thread_info> m_per_scalar_thread; - bool m_mem_accesses_created; - std::list<mem_access_t> m_accessq; + bool accessq_empty() const { return m_accessq.empty(); } + unsigned accessq_count() const { return m_accessq.size(); } + const mem_access_t &accessq_back() { return m_accessq.back(); } + void accessq_pop_back() { m_accessq.pop_back(); } - unsigned m_scheduler_id; //the scheduler that issues this inst + bool dispatch_delay() { + if (cycles > 0) cycles--; + return cycles > 0; + } - //Jin: cdp support -public: - int m_is_cdp; - -}; + bool has_dispatch_delay() { return cycles > 0; } -void move_warp( warp_inst_t *&dst, warp_inst_t *&src ); + void print(FILE *fout) const; + unsigned get_uid() const { return m_uid; } + unsigned get_schd_id() const { return m_scheduler_id; } -size_t get_kernel_code_size( class function_info *entry ); -class checkpoint -{ -public: + protected: + unsigned m_uid; + bool m_empty; + bool m_cache_hit; + unsigned long long issue_cycle; + unsigned cycles; // used for implementing initiation interval delay + bool m_isatomic; + bool m_is_printf; + unsigned m_warp_id; + unsigned m_dynamic_warp_id; + const core_config *m_config; + active_mask_t m_warp_active_mask; // dynamic active mask for timing model + // (after predication) + active_mask_t m_warp_issued_mask; // active mask at issue (prior to + // predication test) -- for instruction + // counting - checkpoint(); - ~checkpoint(){ - printf("clasfsfss destructed\n"); + struct per_thread_info { + per_thread_info() { + for (unsigned i = 0; i < MAX_ACCESSES_PER_INSN_PER_THREAD; i++) + memreqaddr[i] = 0; } + dram_callback_t callback; + new_addr_type memreqaddr[MAX_ACCESSES_PER_INSN_PER_THREAD]; // effective + // address, + // upto 8 + // different + // requests (to + // support 32B + // access in 8 + // chunks of 4B + // each) + }; + bool m_per_scalar_thread_valid; + std::vector<per_thread_info> m_per_scalar_thread; + bool m_mem_accesses_created; + std::list<mem_access_t> m_accessq; - void load_global_mem(class memory_space *temp_mem, char * f1name); - void store_global_mem(class memory_space *mem, char * fname , char * format); - unsigned radnom; + unsigned m_scheduler_id; // the scheduler that issues this inst + // Jin: cdp support + public: + int m_is_cdp; +}; + +void move_warp(warp_inst_t *&dst, warp_inst_t *&src); + +size_t get_kernel_code_size(class function_info *entry); +class checkpoint { + public: + checkpoint(); + ~checkpoint() { printf("clasfsfss destructed\n"); } + void load_global_mem(class memory_space *temp_mem, char *f1name); + void store_global_mem(class memory_space *mem, char *fname, char *format); + unsigned radnom; }; /* - * This abstract class used as a base for functional and performance and simulation, it has basic functional simulation - * data structures and procedures. + * This abstract class used as a base for functional and performance and + * simulation, it has basic functional simulation + * data structures and procedures. */ class core_t { - public: - core_t( gpgpu_sim *gpu, - kernel_info_t *kernel, - unsigned warp_size, - unsigned threads_per_shader ) - : m_gpu( gpu ), - m_kernel( kernel ), - m_simt_stack( NULL ), - m_thread( NULL ), - m_warp_size( warp_size ) - { - m_warp_count = threads_per_shader/m_warp_size; - // Handle the case where the number of threads is not a - // multiple of the warp size - if ( threads_per_shader % m_warp_size != 0 ) { - m_warp_count += 1; - } - assert( m_warp_count * m_warp_size > 0 ); - m_thread = ( ptx_thread_info** ) - calloc( m_warp_count * m_warp_size, - sizeof( ptx_thread_info* ) ); - initilizeSIMTStack(m_warp_count,m_warp_size); + public: + core_t(gpgpu_sim *gpu, kernel_info_t *kernel, unsigned warp_size, + unsigned threads_per_shader) + : m_gpu(gpu), + m_kernel(kernel), + m_simt_stack(NULL), + m_thread(NULL), + m_warp_size(warp_size) { + m_warp_count = threads_per_shader / m_warp_size; + // Handle the case where the number of threads is not a + // multiple of the warp size + if (threads_per_shader % m_warp_size != 0) { + m_warp_count += 1; + } + assert(m_warp_count * m_warp_size > 0); + m_thread = (ptx_thread_info **)calloc(m_warp_count * m_warp_size, + sizeof(ptx_thread_info *)); + initilizeSIMTStack(m_warp_count, m_warp_size); - for(unsigned i=0; i<MAX_CTA_PER_SHADER; i++){ - for(unsigned j=0; j<MAX_BARRIERS_PER_CTA; j++){ - reduction_storage[i][j]=0; - } - } + for (unsigned i = 0; i < MAX_CTA_PER_SHADER; i++) { + for (unsigned j = 0; j < MAX_BARRIERS_PER_CTA; j++) { + reduction_storage[i][j] = 0; + } + } + } + virtual ~core_t() { free(m_thread); } + virtual void warp_exit(unsigned warp_id) = 0; + virtual bool warp_waiting_at_barrier(unsigned warp_id) const = 0; + virtual void checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t, + unsigned tid) = 0; + class gpgpu_sim *get_gpu() { + return m_gpu; + } + void execute_warp_inst_t(warp_inst_t &inst, unsigned warpId = (unsigned)-1); + bool ptx_thread_done(unsigned hw_thread_id) const; + void updateSIMTStack(unsigned warpId, warp_inst_t *inst); + void initilizeSIMTStack(unsigned warp_count, unsigned warps_size); + void deleteSIMTStack(); + warp_inst_t getExecuteWarp(unsigned warpId); + void get_pdom_stack_top_info(unsigned warpId, unsigned *pc, + unsigned *rpc) const; + kernel_info_t *get_kernel_info() { return m_kernel; } + class ptx_thread_info **get_thread_info() { + return m_thread; + } + unsigned get_warp_size() const { return m_warp_size; } + void and_reduction(unsigned ctaid, unsigned barid, bool value) { + reduction_storage[ctaid][barid] &= value; + } + void or_reduction(unsigned ctaid, unsigned barid, bool value) { + reduction_storage[ctaid][barid] |= value; + } + void popc_reduction(unsigned ctaid, unsigned barid, bool value) { + reduction_storage[ctaid][barid] += value; + } + unsigned get_reduction_value(unsigned ctaid, unsigned barid) { + return reduction_storage[ctaid][barid]; + } - } - virtual ~core_t() { free(m_thread); } - virtual void warp_exit( unsigned warp_id ) = 0; - virtual bool warp_waiting_at_barrier( unsigned warp_id ) const = 0; - virtual void checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t, unsigned tid)=0; - class gpgpu_sim * get_gpu() {return m_gpu;} - void execute_warp_inst_t(warp_inst_t &inst, unsigned warpId =(unsigned)-1); - bool ptx_thread_done( unsigned hw_thread_id ) const ; - void updateSIMTStack(unsigned warpId, warp_inst_t * inst); - void initilizeSIMTStack(unsigned warp_count, unsigned warps_size); - void deleteSIMTStack(); - warp_inst_t getExecuteWarp(unsigned warpId); - void get_pdom_stack_top_info( unsigned warpId, unsigned *pc, unsigned *rpc ) const; - kernel_info_t * get_kernel_info(){ return m_kernel;} - class ptx_thread_info ** get_thread_info() { return m_thread; } - unsigned get_warp_size() const { return m_warp_size; } - void and_reduction(unsigned ctaid, unsigned barid, bool value) { reduction_storage[ctaid][barid] &= value; } - void or_reduction(unsigned ctaid, unsigned barid, bool value) { reduction_storage[ctaid][barid] |= value; } - void popc_reduction(unsigned ctaid, unsigned barid, bool value) { reduction_storage[ctaid][barid] += value;} - unsigned get_reduction_value(unsigned ctaid, unsigned barid) {return reduction_storage[ctaid][barid];} - protected: - class gpgpu_sim *m_gpu; - kernel_info_t *m_kernel; - simt_stack **m_simt_stack; // pdom based reconvergence context for each warp - class ptx_thread_info ** m_thread; - unsigned m_warp_size; - unsigned m_warp_count; - unsigned reduction_storage[MAX_CTA_PER_SHADER][MAX_BARRIERS_PER_CTA]; + protected: + class gpgpu_sim *m_gpu; + kernel_info_t *m_kernel; + simt_stack **m_simt_stack; // pdom based reconvergence context for each warp + class ptx_thread_info **m_thread; + unsigned m_warp_size; + unsigned m_warp_count; + unsigned reduction_storage[MAX_CTA_PER_SHADER][MAX_BARRIERS_PER_CTA]; }; - -//register that can hold multiple instructions. +// register that can hold multiple instructions. class register_set { -public: - register_set(unsigned num, const char* name){ - for( unsigned i = 0; i < num; i++ ) { - regs.push_back(new warp_inst_t()); - } - m_name = name; - } - bool has_free(){ - for( unsigned i = 0; i < regs.size(); i++ ) { - if( regs[i]->empty() ) { - return true; - } - } - return false; - } - bool has_free(bool sub_core_model, unsigned reg_id){ - //in subcore model, each sched has a one specific reg to use (based on sched id) - if(!sub_core_model) - return has_free(); + public: + register_set(unsigned num, const char *name) { + for (unsigned i = 0; i < num; i++) { + regs.push_back(new warp_inst_t()); + } + m_name = name; + } + bool has_free() { + for (unsigned i = 0; i < regs.size(); i++) { + if (regs[i]->empty()) { + return true; + } + } + return false; + } + bool has_free(bool sub_core_model, unsigned reg_id) { + // in subcore model, each sched has a one specific reg to use (based on + // sched id) + if (!sub_core_model) return has_free(); - assert(reg_id < regs.size()); - return regs[reg_id]->empty(); - } - bool has_ready(){ - for( unsigned i = 0; i < regs.size(); i++ ) { - if( not regs[i]->empty() ) { - return true; - } - } - return false; - } + assert(reg_id < regs.size()); + return regs[reg_id]->empty(); + } + bool has_ready() { + for (unsigned i = 0; i < regs.size(); i++) { + if (not regs[i]->empty()) { + return true; + } + } + return false; + } - void move_in( warp_inst_t *&src ){ - warp_inst_t** free = get_free(); - move_warp(*free, src); - } - //void copy_in( warp_inst_t* src ){ - // src->copy_contents_to(*get_free()); - //} - void move_out_to( warp_inst_t *&dest ){ - warp_inst_t **ready=get_ready(); - move_warp(dest, *ready); - } + void move_in(warp_inst_t *&src) { + warp_inst_t **free = get_free(); + move_warp(*free, src); + } + // void copy_in( warp_inst_t* src ){ + // src->copy_contents_to(*get_free()); + //} + void move_out_to(warp_inst_t *&dest) { + warp_inst_t **ready = get_ready(); + move_warp(dest, *ready); + } - warp_inst_t** get_ready(){ - warp_inst_t** ready; - ready = NULL; - for( unsigned i = 0; i < regs.size(); i++ ) { - if( not regs[i]->empty() ) { - if( ready and (*ready)->get_uid() < regs[i]->get_uid() ) { - // ready is oldest - } else { - ready = ®s[i]; - } - } - } - return ready; - } + warp_inst_t **get_ready() { + warp_inst_t **ready; + ready = NULL; + for (unsigned i = 0; i < regs.size(); i++) { + if (not regs[i]->empty()) { + if (ready and (*ready)->get_uid() < regs[i]->get_uid()) { + // ready is oldest + } else { + ready = ®s[i]; + } + } + } + return ready; + } - void print(FILE* fp) const{ - fprintf(fp, "%s : @%p\n", m_name, this); - for( unsigned i = 0; i < regs.size(); i++ ) { - fprintf(fp, " "); - regs[i]->print(fp); - fprintf(fp, "\n"); - } - } + void print(FILE *fp) const { + fprintf(fp, "%s : @%p\n", m_name, this); + for (unsigned i = 0; i < regs.size(); i++) { + fprintf(fp, " "); + regs[i]->print(fp); + fprintf(fp, "\n"); + } + } - warp_inst_t ** get_free(){ - for( unsigned i = 0; i < regs.size(); i++ ) { - if( regs[i]->empty() ) { - return ®s[i]; - } - } - assert(0 && "No free registers found"); - return NULL; - } + warp_inst_t **get_free() { + for (unsigned i = 0; i < regs.size(); i++) { + if (regs[i]->empty()) { + return ®s[i]; + } + } + assert(0 && "No free registers found"); + return NULL; + } - warp_inst_t ** get_free(bool sub_core_model, unsigned reg_id){ - //in subcore model, each sched has a one specific reg to use (based on sched id) - if(!sub_core_model) - return get_free(); + warp_inst_t **get_free(bool sub_core_model, unsigned reg_id) { + // in subcore model, each sched has a one specific reg to use (based on + // sched id) + if (!sub_core_model) return get_free(); - assert(reg_id < regs.size()); - if( regs[reg_id]->empty() ) { - return ®s[reg_id]; - } - assert(0 && "No free register found"); - return NULL; - } + assert(reg_id < regs.size()); + if (regs[reg_id]->empty()) { + return ®s[reg_id]; + } + assert(0 && "No free register found"); + return NULL; + } - unsigned get_size(){ - return regs.size(); - } + unsigned get_size() { return regs.size(); } -private: - std::vector<warp_inst_t*> regs; - const char* m_name; + private: + std::vector<warp_inst_t *> regs; + const char *m_name; }; -#endif // #ifdef __cplusplus +#endif // #ifdef __cplusplus -#endif // #ifndef ABSTRACT_HARDWARE_MODEL_INCLUDED +#endif // #ifndef ABSTRACT_HARDWARE_MODEL_INCLUDED diff --git a/src/debug.cc b/src/debug.cc index c00ff9e..eaf39a6 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -7,14 +7,16 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this +// Redistributions in binary form must reproduce the above copyright notice, +// this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -26,183 +28,197 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "debug.h" -#include "gpgpu-sim/shader.h" -#include "gpgpu-sim/gpu-sim.h" -#include "cuda-sim/ptx_sim.h" #include "cuda-sim/cuda-sim.h" #include "cuda-sim/ptx_ir.h" +#include "cuda-sim/ptx_sim.h" +#include "gpgpu-sim/gpu-sim.h" +#include "gpgpu-sim/shader.h" -#include <map> #include <stdio.h> #include <string.h> +#include <map> -void gpgpu_sim::hit_watchpoint( unsigned watchpoint_num, ptx_thread_info *thd, const ptx_instruction *pI ) -{ - g_watchpoint_hits[watchpoint_num]=watchpoint_event(thd,pI); +void gpgpu_sim::hit_watchpoint(unsigned watchpoint_num, ptx_thread_info *thd, + const ptx_instruction *pI) { + g_watchpoint_hits[watchpoint_num] = watchpoint_event(thd, pI); } -/// interactive debugger +/// interactive debugger -void gpgpu_sim::gpgpu_debug() -{ - bool done=true; +void gpgpu_sim::gpgpu_debug() { + bool done = true; - static bool single_step=true; - static unsigned next_brkpt=1; - static std::map<unsigned,brk_pt> breakpoints; + static bool single_step = true; + static unsigned next_brkpt = 1; + static std::map<unsigned, brk_pt> breakpoints; - /// if single stepping, go to interactive debugger + /// if single stepping, go to interactive debugger - if( single_step ) - done=false; + if (single_step) done = false; - /// check if we've reached a breakpoint - const ptx_thread_info *brk_thd = NULL; - const ptx_instruction *brk_inst = NULL; + /// check if we've reached a breakpoint + const ptx_thread_info *brk_thd = NULL; + const ptx_instruction *brk_inst = NULL; - for( std::map<unsigned,brk_pt>::iterator i=breakpoints.begin(); i!=breakpoints.end(); i++) { - unsigned num=i->first; - brk_pt &b=i->second; - if( b.is_watchpoint() ) { - unsigned addr = b.get_addr(); - unsigned new_value; - m_global_mem->read(addr,4,&new_value); - if( new_value != b.get_value() || g_watchpoint_hits.find(num) != g_watchpoint_hits.end() ) { - printf( "GPGPU-Sim PTX DBG: watch point %u triggered (old value=%x, new value=%x)\n", - num,b.get_value(),new_value ); - std::map<unsigned,watchpoint_event>::iterator w=g_watchpoint_hits.find(num); - if( w==g_watchpoint_hits.end() ) - printf( "GPGPU-Sim PTX DBG: memory transfer modified value\n"); - else { - watchpoint_event wa = w->second; - brk_thd = wa.thread(); - brk_inst = wa.inst(); - printf( "GPGPU-Sim PTX DBG: modified by thread uid=%u, sid=%u, hwtid=%u\n", - brk_thd->get_uid(),brk_thd->get_hw_sid(), brk_thd->get_hw_tid() ); - printf( "GPGPU-Sim PTX DBG: "); - brk_inst->print_insn(stdout); - printf( "\n" ); - g_watchpoint_hits.erase(w); - } - b.set_value(new_value); - done = false; - } - } else { - /* - for( unsigned sid=0; sid < m_n_shader; sid++ ) { - unsigned hw_thread_id = -1; - abort(); - ptx_thread_info *thread = m_sc[sid]->get_functional_thread(hw_thread_id); - if( thread_at_brkpt(thread, b) ) { - done = false; - printf("GPGPU-Sim PTX DBG: reached breakpoint %u at %s (sm=%u, hwtid=%u)\n", - num, b.location().c_str(), sid, hw_thread_id ); - brk_thd = thread; - brk_inst = brk_thd->get_inst(); - printf( "GPGPU-Sim PTX DBG: reached by thread uid=%u, sid=%u, hwtid=%u\n", - brk_thd->get_uid(),brk_thd->get_hw_sid(), brk_thd->get_hw_tid() ); - printf( "GPGPU-Sim PTX DBG: "); - brk_inst->print_insn(stdout); - printf( "\n" ); - } - } - */ + for (std::map<unsigned, brk_pt>::iterator i = breakpoints.begin(); + i != breakpoints.end(); i++) { + unsigned num = i->first; + brk_pt &b = i->second; + if (b.is_watchpoint()) { + unsigned addr = b.get_addr(); + unsigned new_value; + m_global_mem->read(addr, 4, &new_value); + if (new_value != b.get_value() || + g_watchpoint_hits.find(num) != g_watchpoint_hits.end()) { + printf( + "GPGPU-Sim PTX DBG: watch point %u triggered (old value=%x, new " + "value=%x)\n", + num, b.get_value(), new_value); + std::map<unsigned, watchpoint_event>::iterator w = + g_watchpoint_hits.find(num); + if (w == g_watchpoint_hits.end()) + printf("GPGPU-Sim PTX DBG: memory transfer modified value\n"); + else { + watchpoint_event wa = w->second; + brk_thd = wa.thread(); + brk_inst = wa.inst(); + printf( + "GPGPU-Sim PTX DBG: modified by thread uid=%u, sid=%u, " + "hwtid=%u\n", + brk_thd->get_uid(), brk_thd->get_hw_sid(), brk_thd->get_hw_tid()); + printf("GPGPU-Sim PTX DBG: "); + brk_inst->print_insn(stdout); + printf("\n"); + g_watchpoint_hits.erase(w); + } + b.set_value(new_value); + done = false; } - } + } else { + /* + for( unsigned sid=0; sid < m_n_shader; sid++ ) { + unsigned hw_thread_id = -1; + abort(); + ptx_thread_info *thread = + m_sc[sid]->get_functional_thread(hw_thread_id); + if( thread_at_brkpt(thread, b) ) { + done = false; + printf("GPGPU-Sim PTX DBG: reached breakpoint %u at %s (sm=%u, + hwtid=%u)\n", + num, b.location().c_str(), sid, hw_thread_id ); + brk_thd = thread; + brk_inst = brk_thd->get_inst(); + printf( "GPGPU-Sim PTX DBG: reached by thread uid=%u, sid=%u, + hwtid=%u\n", + brk_thd->get_uid(),brk_thd->get_hw_sid(), + brk_thd->get_hw_tid() ); + printf( "GPGPU-Sim PTX DBG: "); + brk_inst->print_insn(stdout); + printf( "\n" ); + } + } + */ + } + } - if( done ) - assert( g_watchpoint_hits.empty() ); + if (done) assert(g_watchpoint_hits.empty()); - /// enter interactive debugger loop + /// enter interactive debugger loop - while (!done) { - printf("(ptx debugger) "); - fflush(stdout); - - char line[1024]; - fgets(line,1024,stdin); + while (!done) { + printf("(ptx debugger) "); + fflush(stdout); - char *tok = strtok(line," \t\n"); - if( !strcmp(tok,"dp") ) { - int shader_num = 0; - tok = strtok(NULL," \t\n"); - sscanf(tok,"%d",&shader_num); - dump_pipeline((0x40|0x4|0x1),shader_num,0); - printf("\n"); - fflush(stdout); - } else if( !strcmp(tok,"q") || !strcmp(tok,"quit") ) { - printf("\nreally quit GPGPU-Sim (y/n)?\n"); - fgets(line,1024,stdin); - tok = strtok(line," \t\n"); - if( !strcmp(tok,"y") ) { - exit(0); - } else { - printf("not quiting.\n"); - } - } else if( !strcmp(tok,"b") ) { - tok = strtok(NULL," \t\n"); - char brkpt[1024]; - sscanf(tok,"%s",brkpt); - tok = strtok(NULL," \t\n"); - unsigned uid; - sscanf(tok,"%u",&uid); - breakpoints[next_brkpt++] = brk_pt(brkpt,uid); - } else if( !strcmp(tok,"d") ) { - tok = strtok(NULL," \t\n"); - unsigned uid; - sscanf(tok,"%u",&uid); - breakpoints.erase(uid); - } else if( !strcmp(tok,"s") ) { - done = true; - } else if( !strcmp(tok,"c") ) { - single_step=false; - done = true; - } else if( !strcmp(tok,"w") ) { - tok = strtok(NULL," \t\n"); - unsigned addr; - sscanf(tok,"%x",&addr); - unsigned value; - m_global_mem->read(addr,4,&value); - m_global_mem->set_watch(addr,next_brkpt); - breakpoints[next_brkpt++] = brk_pt(addr,value); - } else if( !strcmp(tok,"l") ) { - if( brk_thd == NULL ) { - printf("no thread selected\n"); - } else { - addr_t pc = brk_thd->get_pc(); - addr_t start_pc = (pc<5)?0:(pc-5); - for( addr_t p=start_pc; p <= pc+5; p++ ) { - const ptx_instruction *i = brk_thd->get_inst(p); - if( i ) { - if( p != pc ) - printf( " " ); - else - printf( "==> " ); - i->print_insn(stdout); - printf( "\n" ); - } - } - } - } else if( !strcmp(tok,"h") ) { - printf("commands:\n"); - printf(" q - quit GPGPU-Sim\n"); - printf(" b <file>:<line> <thead uid> - set breakpoint\n"); - printf(" w <global address> - set watchpoint\n"); - printf(" del <n> - delete breakpoint\n"); - printf(" s - single step one shader cycle (all cores)\n"); - printf(" c - continue simulation without single stepping\n"); - printf(" l - list PTX around current breakpoint\n"); - printf(" dp <n> - display pipeline contents on SM <n>\n"); - printf(" h - print this message\n"); + char line[1024]; + fgets(line, 1024, stdin); + + char *tok = strtok(line, " \t\n"); + if (!strcmp(tok, "dp")) { + int shader_num = 0; + tok = strtok(NULL, " \t\n"); + sscanf(tok, "%d", &shader_num); + dump_pipeline((0x40 | 0x4 | 0x1), shader_num, 0); + printf("\n"); + fflush(stdout); + } else if (!strcmp(tok, "q") || !strcmp(tok, "quit")) { + printf("\nreally quit GPGPU-Sim (y/n)?\n"); + fgets(line, 1024, stdin); + tok = strtok(line, " \t\n"); + if (!strcmp(tok, "y")) { + exit(0); } else { - printf("\ncommand not understood.\n"); + printf("not quiting.\n"); } - fflush(stdout); - } + } else if (!strcmp(tok, "b")) { + tok = strtok(NULL, " \t\n"); + char brkpt[1024]; + sscanf(tok, "%s", brkpt); + tok = strtok(NULL, " \t\n"); + unsigned uid; + sscanf(tok, "%u", &uid); + breakpoints[next_brkpt++] = brk_pt(brkpt, uid); + } else if (!strcmp(tok, "d")) { + tok = strtok(NULL, " \t\n"); + unsigned uid; + sscanf(tok, "%u", &uid); + breakpoints.erase(uid); + } else if (!strcmp(tok, "s")) { + done = true; + } else if (!strcmp(tok, "c")) { + single_step = false; + done = true; + } else if (!strcmp(tok, "w")) { + tok = strtok(NULL, " \t\n"); + unsigned addr; + sscanf(tok, "%x", &addr); + unsigned value; + m_global_mem->read(addr, 4, &value); + m_global_mem->set_watch(addr, next_brkpt); + breakpoints[next_brkpt++] = brk_pt(addr, value); + } else if (!strcmp(tok, "l")) { + if (brk_thd == NULL) { + printf("no thread selected\n"); + } else { + addr_t pc = brk_thd->get_pc(); + addr_t start_pc = (pc < 5) ? 0 : (pc - 5); + for (addr_t p = start_pc; p <= pc + 5; p++) { + const ptx_instruction *i = brk_thd->get_inst(p); + if (i) { + if (p != pc) + printf(" "); + else + printf("==> "); + i->print_insn(stdout); + printf("\n"); + } + } + } + } else if (!strcmp(tok, "h")) { + printf("commands:\n"); + printf(" q - quit GPGPU-Sim\n"); + printf(" b <file>:<line> <thead uid> - set breakpoint\n"); + printf(" w <global address> - set watchpoint\n"); + printf(" del <n> - delete breakpoint\n"); + printf( + " s - single step one shader cycle (all " + "cores)\n"); + printf( + " c - continue simulation without single " + "stepping\n"); + printf( + " l - list PTX around current " + "breakpoint\n"); + printf( + " dp <n> - display pipeline contents on SM " + "<n>\n"); + printf(" h - print this message\n"); + } else { + printf("\ncommand not understood.\n"); + } + fflush(stdout); + } } -bool thread_at_brkpt( ptx_thread_info *thread, const class brk_pt &b ) -{ - return b.is_equal(thread->get_location(),thread->get_uid()); +bool thread_at_brkpt(ptx_thread_info *thread, const class brk_pt &b) { + return b.is_equal(thread->get_location(), thread->get_uid()); } - diff --git a/src/debug.h b/src/debug.h index 4e79a9f..2799efe 100644 --- a/src/debug.h +++ b/src/debug.h @@ -7,14 +7,16 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this +// Redistributions in binary form must reproduce the above copyright notice, +// this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -33,58 +35,53 @@ #include <string> class brk_pt { -public: - brk_pt() { m_valid=false; } - brk_pt( const char *fileline, unsigned uid ) - { - m_valid = true; - m_watch = false; - m_fileline = std::string(fileline); - m_thread_uid=uid; - } - brk_pt( unsigned addr, unsigned value ) - { - m_valid = true; - m_watch = true; - m_addr = addr; - m_value = value; - } + public: + brk_pt() { m_valid = false; } + brk_pt(const char *fileline, unsigned uid) { + m_valid = true; + m_watch = false; + m_fileline = std::string(fileline); + m_thread_uid = uid; + } + brk_pt(unsigned addr, unsigned value) { + m_valid = true; + m_watch = true; + m_addr = addr; + m_value = value; + } - unsigned get_value() const { return m_value; } - addr_t get_addr() const { return m_addr; } - bool is_valid() const { return m_valid; } - bool is_watchpoint() const { return m_watch; } - bool is_equal( const std::string &fileline, unsigned uid ) const - { - if( m_watch ) - return false; - if( (m_thread_uid != (unsigned)-1) && (uid != m_thread_uid) ) - return false; - return m_fileline == fileline; - } - std::string location() const - { - char buffer[1024]; - sprintf(buffer,"%s thread uid = %u", m_fileline.c_str(), m_thread_uid); - return buffer; - } + unsigned get_value() const { return m_value; } + addr_t get_addr() const { return m_addr; } + bool is_valid() const { return m_valid; } + bool is_watchpoint() const { return m_watch; } + bool is_equal(const std::string &fileline, unsigned uid) const { + if (m_watch) return false; + if ((m_thread_uid != (unsigned)-1) && (uid != m_thread_uid)) return false; + return m_fileline == fileline; + } + std::string location() const { + char buffer[1024]; + sprintf(buffer, "%s thread uid = %u", m_fileline.c_str(), m_thread_uid); + return buffer; + } - unsigned set_value( unsigned val ) { return m_value=val; } -private: - bool m_valid; - bool m_watch; + unsigned set_value(unsigned val) { return m_value = val; } - // break point - std::string m_fileline; - unsigned m_thread_uid; + private: + bool m_valid; + bool m_watch; - // watch point - unsigned m_addr; - unsigned m_value; + // break point + std::string m_fileline; + unsigned m_thread_uid; + + // watch point + unsigned m_addr; + unsigned m_value; }; class ptx_thread_info; class ptx_instruction; -bool thread_at_brkpt( ptx_thread_info *thd_info, const class brk_pt &b ); +bool thread_at_brkpt(ptx_thread_info *thd_info, const class brk_pt &b); #endif diff --git a/src/gpgpusim_entrypoint.cc b/src/gpgpusim_entrypoint.cc index 846773d..04aa3f8 100644 --- a/src/gpgpusim_entrypoint.cc +++ b/src/gpgpusim_entrypoint.cc @@ -7,14 +7,16 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this +// Redistributions in binary form must reproduce the above copyright notice, +// this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -28,253 +30,266 @@ #include "gpgpusim_entrypoint.h" #include <stdio.h> -#include "option_parser.h" +#include "../libcuda/gpgpu_context.h" #include "cuda-sim/cuda-sim.h" #include "cuda-sim/ptx_ir.h" #include "cuda-sim/ptx_parser.h" #include "gpgpu-sim/gpu-sim.h" #include "gpgpu-sim/icnt_wrapper.h" +#include "option_parser.h" #include "stream_manager.h" -#include "../libcuda/gpgpu_context.h" -#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) static int sg_argc = 3; -static const char *sg_argv[] = {"", "-config","gpgpusim.config"}; - +static const char *sg_argv[] = {"", "-config", "gpgpusim.config"}; -void * gpgpu_sim_thread_sequential(void * ctx_ptr) -{ - gpgpu_context * ctx = (gpgpu_context *)ctx_ptr; - // at most one kernel running at a time - bool done; - do { - sem_wait(&(ctx->the_gpgpusim->g_sim_signal_start)); - done = true; - if( ctx->the_gpgpusim->g_the_gpu->get_more_cta_left() ) { - done = false; - ctx->the_gpgpusim->g_the_gpu->init(); - while( ctx->the_gpgpusim->g_the_gpu->active() ) { - ctx->the_gpgpusim->g_the_gpu->cycle(); - ctx->the_gpgpusim->g_the_gpu->deadlock_check(); - } - ctx->the_gpgpusim->g_the_gpu->print_stats(); - ctx->the_gpgpusim->g_the_gpu->update_stats(); - ctx->print_simulation_time(); +void *gpgpu_sim_thread_sequential(void *ctx_ptr) { + gpgpu_context *ctx = (gpgpu_context *)ctx_ptr; + // at most one kernel running at a time + bool done; + do { + sem_wait(&(ctx->the_gpgpusim->g_sim_signal_start)); + done = true; + if (ctx->the_gpgpusim->g_the_gpu->get_more_cta_left()) { + done = false; + ctx->the_gpgpusim->g_the_gpu->init(); + while (ctx->the_gpgpusim->g_the_gpu->active()) { + ctx->the_gpgpusim->g_the_gpu->cycle(); + ctx->the_gpgpusim->g_the_gpu->deadlock_check(); } - sem_post(&(ctx->the_gpgpusim->g_sim_signal_finish)); - } while(!done); - sem_post(&(ctx->the_gpgpusim->g_sim_signal_exit)); - return NULL; + ctx->the_gpgpusim->g_the_gpu->print_stats(); + ctx->the_gpgpusim->g_the_gpu->update_stats(); + ctx->print_simulation_time(); + } + sem_post(&(ctx->the_gpgpusim->g_sim_signal_finish)); + } while (!done); + sem_post(&(ctx->the_gpgpusim->g_sim_signal_exit)); + return NULL; } - - -static void termination_callback() -{ - printf("GPGPU-Sim: *** exit detected ***\n"); - fflush(stdout); +static void termination_callback() { + printf("GPGPU-Sim: *** exit detected ***\n"); + fflush(stdout); } -void *gpgpu_sim_thread_concurrent(void * ctx_ptr) -{ - gpgpu_context * ctx = (gpgpu_context *)ctx_ptr; - atexit(termination_callback); - // concurrent kernel execution simulation thread +void *gpgpu_sim_thread_concurrent(void *ctx_ptr) { + gpgpu_context *ctx = (gpgpu_context *)ctx_ptr; + atexit(termination_callback); + // concurrent kernel execution simulation thread + do { + if (g_debug_execution >= 3) { + printf( + "GPGPU-Sim: *** simulation thread starting and spinning waiting for " + "work ***\n"); + fflush(stdout); + } + while (ctx->the_gpgpusim->g_stream_manager->empty_protected() && + !ctx->the_gpgpusim->g_sim_done) + ; + if (g_debug_execution >= 3) { + printf("GPGPU-Sim: ** START simulation thread (detected work) **\n"); + ctx->the_gpgpusim->g_stream_manager->print(stdout); + fflush(stdout); + } + pthread_mutex_lock(&(ctx->the_gpgpusim->g_sim_lock)); + ctx->the_gpgpusim->g_sim_active = true; + pthread_mutex_unlock(&(ctx->the_gpgpusim->g_sim_lock)); + bool active = false; + bool sim_cycles = false; + ctx->the_gpgpusim->g_the_gpu->init(); do { - if(g_debug_execution >= 3) { - printf("GPGPU-Sim: *** simulation thread starting and spinning waiting for work ***\n"); - fflush(stdout); - } - while( ctx->the_gpgpusim->g_stream_manager->empty_protected() && !ctx->the_gpgpusim->g_sim_done ) - ; - if(g_debug_execution >= 3) { - printf("GPGPU-Sim: ** START simulation thread (detected work) **\n"); - ctx->the_gpgpusim->g_stream_manager->print(stdout); - fflush(stdout); - } - pthread_mutex_lock(&(ctx->the_gpgpusim->g_sim_lock)); - ctx->the_gpgpusim->g_sim_active = true; - pthread_mutex_unlock(&(ctx->the_gpgpusim->g_sim_lock)); - bool active = false; - bool sim_cycles = false; - ctx->the_gpgpusim->g_the_gpu->init(); - do { - // check if a kernel has completed - // launch operation on device if one is pending and can be run - - // Need to break this loop when a kernel completes. This was a - // source of non-deterministic behaviour in GPGPU-Sim (bug 147). - // If another stream operation is available, g_the_gpu remains active, - // causing this loop to not break. If the next operation happens to be - // another kernel, the gpu is not re-initialized and the inter-kernel - // behaviour may be incorrect. Check that a kernel has finished and - // no other kernel is currently running. - if(ctx->the_gpgpusim->g_stream_manager->operation(&sim_cycles) && !ctx->the_gpgpusim->g_the_gpu->active()) - break; - - //functional simulation - if( ctx->the_gpgpusim->g_the_gpu->is_functional_sim()) { - kernel_info_t * kernel = ctx->the_gpgpusim->g_the_gpu->get_functional_kernel(); - assert(kernel); - ctx->the_gpgpusim->gpgpu_ctx->func_sim->gpgpu_cuda_ptx_sim_main_func(*kernel); - ctx->the_gpgpusim->g_the_gpu->finish_functional_sim(kernel); - } + // check if a kernel has completed + // launch operation on device if one is pending and can be run - //performance simulation - if( ctx->the_gpgpusim->g_the_gpu->active() ) { - ctx->the_gpgpusim->g_the_gpu->cycle(); - sim_cycles = true; - ctx->the_gpgpusim->g_the_gpu->deadlock_check(); - }else { - if(ctx->the_gpgpusim->g_the_gpu->cycle_insn_cta_max_hit()){ - ctx->the_gpgpusim->g_stream_manager->stop_all_running_kernels(); - ctx->the_gpgpusim->g_sim_done = true; - ctx->the_gpgpusim->break_limit = true; - } - } + // Need to break this loop when a kernel completes. This was a + // source of non-deterministic behaviour in GPGPU-Sim (bug 147). + // If another stream operation is available, g_the_gpu remains active, + // causing this loop to not break. If the next operation happens to be + // another kernel, the gpu is not re-initialized and the inter-kernel + // behaviour may be incorrect. Check that a kernel has finished and + // no other kernel is currently running. + if (ctx->the_gpgpusim->g_stream_manager->operation(&sim_cycles) && + !ctx->the_gpgpusim->g_the_gpu->active()) + break; - active=ctx->the_gpgpusim->g_the_gpu->active() || !(ctx->the_gpgpusim->g_stream_manager->empty_protected()); + // functional simulation + if (ctx->the_gpgpusim->g_the_gpu->is_functional_sim()) { + kernel_info_t *kernel = + ctx->the_gpgpusim->g_the_gpu->get_functional_kernel(); + assert(kernel); + ctx->the_gpgpusim->gpgpu_ctx->func_sim->gpgpu_cuda_ptx_sim_main_func( + *kernel); + ctx->the_gpgpusim->g_the_gpu->finish_functional_sim(kernel); + } - } while( active && !ctx->the_gpgpusim->g_sim_done); - if(g_debug_execution >= 3) { - printf("GPGPU-Sim: ** STOP simulation thread (no work) **\n"); - fflush(stdout); - } - if(sim_cycles) { - ctx->the_gpgpusim->g_the_gpu->print_stats(); - ctx->the_gpgpusim->g_the_gpu->update_stats(); - ctx->print_simulation_time(); + // performance simulation + if (ctx->the_gpgpusim->g_the_gpu->active()) { + ctx->the_gpgpusim->g_the_gpu->cycle(); + sim_cycles = true; + ctx->the_gpgpusim->g_the_gpu->deadlock_check(); + } else { + if (ctx->the_gpgpusim->g_the_gpu->cycle_insn_cta_max_hit()) { + ctx->the_gpgpusim->g_stream_manager->stop_all_running_kernels(); + ctx->the_gpgpusim->g_sim_done = true; + ctx->the_gpgpusim->break_limit = true; } - pthread_mutex_lock(&(ctx->the_gpgpusim->g_sim_lock)); - ctx->the_gpgpusim->g_sim_active = false; - pthread_mutex_unlock(&(ctx->the_gpgpusim->g_sim_lock)); - } while( !ctx->the_gpgpusim->g_sim_done ); + } - printf("GPGPU-Sim: *** simulation thread exiting ***\n"); - fflush(stdout); + active = ctx->the_gpgpusim->g_the_gpu->active() || + !(ctx->the_gpgpusim->g_stream_manager->empty_protected()); - if(ctx->the_gpgpusim->break_limit) { - printf("GPGPU-Sim: ** break due to reaching the maximum cycles (or instructions) **\n"); - exit(1); + } while (active && !ctx->the_gpgpusim->g_sim_done); + if (g_debug_execution >= 3) { + printf("GPGPU-Sim: ** STOP simulation thread (no work) **\n"); + fflush(stdout); } + if (sim_cycles) { + ctx->the_gpgpusim->g_the_gpu->print_stats(); + ctx->the_gpgpusim->g_the_gpu->update_stats(); + ctx->print_simulation_time(); + } + pthread_mutex_lock(&(ctx->the_gpgpusim->g_sim_lock)); + ctx->the_gpgpusim->g_sim_active = false; + pthread_mutex_unlock(&(ctx->the_gpgpusim->g_sim_lock)); + } while (!ctx->the_gpgpusim->g_sim_done); + + printf("GPGPU-Sim: *** simulation thread exiting ***\n"); + fflush(stdout); + + if (ctx->the_gpgpusim->break_limit) { + printf( + "GPGPU-Sim: ** break due to reaching the maximum cycles (or " + "instructions) **\n"); + exit(1); + } - sem_post(&(ctx->the_gpgpusim->g_sim_signal_exit)); - return NULL; + sem_post(&(ctx->the_gpgpusim->g_sim_signal_exit)); + return NULL; } -void gpgpu_context::synchronize() -{ - printf("GPGPU-Sim: synchronize waiting for inactive GPU simulation\n"); - the_gpgpusim->g_stream_manager->print(stdout); - fflush(stdout); -// sem_wait(&g_sim_signal_finish); - bool done = false; - do { - pthread_mutex_lock(&(the_gpgpusim->g_sim_lock)); - done = ( the_gpgpusim->g_stream_manager->empty() && !the_gpgpusim->g_sim_active ) || the_gpgpusim->g_sim_done; - pthread_mutex_unlock(&(the_gpgpusim->g_sim_lock)); - } while (!done); - printf("GPGPU-Sim: detected inactive GPU simulation thread\n"); - fflush(stdout); -// sem_post(&g_sim_signal_start); +void gpgpu_context::synchronize() { + printf("GPGPU-Sim: synchronize waiting for inactive GPU simulation\n"); + the_gpgpusim->g_stream_manager->print(stdout); + fflush(stdout); + // sem_wait(&g_sim_signal_finish); + bool done = false; + do { + pthread_mutex_lock(&(the_gpgpusim->g_sim_lock)); + done = (the_gpgpusim->g_stream_manager->empty() && + !the_gpgpusim->g_sim_active) || + the_gpgpusim->g_sim_done; + pthread_mutex_unlock(&(the_gpgpusim->g_sim_lock)); + } while (!done); + printf("GPGPU-Sim: detected inactive GPU simulation thread\n"); + fflush(stdout); + // sem_post(&g_sim_signal_start); } -void gpgpu_context::exit_simulation() -{ - the_gpgpusim->g_sim_done=true; - printf("GPGPU-Sim: exit_simulation called\n"); - fflush(stdout); - sem_wait(&(the_gpgpusim->g_sim_signal_exit)); - printf("GPGPU-Sim: simulation thread signaled exit\n"); - fflush(stdout); +void gpgpu_context::exit_simulation() { + the_gpgpusim->g_sim_done = true; + printf("GPGPU-Sim: exit_simulation called\n"); + fflush(stdout); + sem_wait(&(the_gpgpusim->g_sim_signal_exit)); + printf("GPGPU-Sim: simulation thread signaled exit\n"); + fflush(stdout); } -gpgpu_sim *gpgpu_context::gpgpu_ptx_sim_init_perf() -{ - srand(1); - print_splash(); - func_sim->read_sim_environment_variables(); - ptx_parser->read_parser_environment_variables(); - option_parser_t opp = option_parser_create(); +gpgpu_sim *gpgpu_context::gpgpu_ptx_sim_init_perf() { + srand(1); + print_splash(); + func_sim->read_sim_environment_variables(); + ptx_parser->read_parser_environment_variables(); + option_parser_t opp = option_parser_create(); - ptx_reg_options(opp); - func_sim->ptx_opcocde_latency_options(opp); + ptx_reg_options(opp); + func_sim->ptx_opcocde_latency_options(opp); - icnt_reg_options(opp); - the_gpgpusim->g_the_gpu_config = new gpgpu_sim_config(this); - the_gpgpusim->g_the_gpu_config->reg_options(opp); // register GPU microrachitecture options + icnt_reg_options(opp); + the_gpgpusim->g_the_gpu_config = new gpgpu_sim_config(this); + the_gpgpusim->g_the_gpu_config->reg_options( + opp); // register GPU microrachitecture options - option_parser_cmdline(opp, sg_argc, sg_argv); // parse configuration options - fprintf(stdout, "GPGPU-Sim: Configuration options:\n\n"); - option_parser_print(opp, stdout); - // Set the Numeric locale to a standard locale where a decimal point is a "dot" not a "comma" - // so it does the parsing correctly independent of the system environment variables - assert(setlocale(LC_NUMERIC,"C")); - the_gpgpusim->g_the_gpu_config->init(); + option_parser_cmdline(opp, sg_argc, sg_argv); // parse configuration options + fprintf(stdout, "GPGPU-Sim: Configuration options:\n\n"); + option_parser_print(opp, stdout); + // Set the Numeric locale to a standard locale where a decimal point is a + // "dot" not a "comma" + // so it does the parsing correctly independent of the system environment + // variables + assert(setlocale(LC_NUMERIC, "C")); + the_gpgpusim->g_the_gpu_config->init(); - the_gpgpusim->g_the_gpu = new gpgpu_sim(*(the_gpgpusim->g_the_gpu_config), this); - the_gpgpusim->g_stream_manager = new stream_manager((the_gpgpusim->g_the_gpu), func_sim->g_cuda_launch_blocking); + the_gpgpusim->g_the_gpu = + new gpgpu_sim(*(the_gpgpusim->g_the_gpu_config), this); + the_gpgpusim->g_stream_manager = new stream_manager( + (the_gpgpusim->g_the_gpu), func_sim->g_cuda_launch_blocking); - the_gpgpusim->g_simulation_starttime = time((time_t *)NULL); + the_gpgpusim->g_simulation_starttime = time((time_t *)NULL); - sem_init(&(the_gpgpusim->g_sim_signal_start),0,0); - sem_init(&(the_gpgpusim->g_sim_signal_finish),0,0); - sem_init(&(the_gpgpusim->g_sim_signal_exit),0,0); + sem_init(&(the_gpgpusim->g_sim_signal_start), 0, 0); + sem_init(&(the_gpgpusim->g_sim_signal_finish), 0, 0); + sem_init(&(the_gpgpusim->g_sim_signal_exit), 0, 0); - return the_gpgpusim->g_the_gpu; + return the_gpgpusim->g_the_gpu; } -void gpgpu_context::start_sim_thread(int api) -{ - if( the_gpgpusim->g_sim_done ) { - the_gpgpusim->g_sim_done = false; - if( api == 1 ) { - pthread_create(&(the_gpgpusim->g_simulation_thread),NULL,gpgpu_sim_thread_concurrent,(void *)this); - } else { - pthread_create(&(the_gpgpusim->g_simulation_thread),NULL,gpgpu_sim_thread_sequential,(void *)this); - } +void gpgpu_context::start_sim_thread(int api) { + if (the_gpgpusim->g_sim_done) { + the_gpgpusim->g_sim_done = false; + if (api == 1) { + pthread_create(&(the_gpgpusim->g_simulation_thread), NULL, + gpgpu_sim_thread_concurrent, (void *)this); + } else { + pthread_create(&(the_gpgpusim->g_simulation_thread), NULL, + gpgpu_sim_thread_sequential, (void *)this); } + } } -void gpgpu_context::print_simulation_time() -{ - time_t current_time, difference, d, h, m, s; - current_time = time((time_t *)NULL); - difference = MAX(current_time - the_gpgpusim->g_simulation_starttime, 1); +void gpgpu_context::print_simulation_time() { + time_t current_time, difference, d, h, m, s; + current_time = time((time_t *)NULL); + difference = MAX(current_time - the_gpgpusim->g_simulation_starttime, 1); - d = difference/(3600*24); - h = difference/3600 - 24*d; - m = difference/60 - 60*(h + 24*d); - s = difference - 60*(m + 60*(h + 24*d)); + d = difference / (3600 * 24); + h = difference / 3600 - 24 * d; + m = difference / 60 - 60 * (h + 24 * d); + s = difference - 60 * (m + 60 * (h + 24 * d)); - fflush(stderr); - printf("\n\ngpgpu_simulation_time = %u days, %u hrs, %u min, %u sec (%u sec)\n", - (unsigned)d, (unsigned)h, (unsigned)m, (unsigned)s, (unsigned)difference ); - printf("gpgpu_simulation_rate = %u (inst/sec)\n", (unsigned)(the_gpgpusim->g_the_gpu->gpu_tot_sim_insn / difference) ); - const unsigned cycles_per_sec = (unsigned)(the_gpgpusim->g_the_gpu->gpu_tot_sim_cycle / difference); - printf("gpgpu_simulation_rate = %u (cycle/sec)\n", cycles_per_sec ); - printf("gpgpu_silicon_slowdown = %ux\n", the_gpgpusim->g_the_gpu->shader_clock() * 1000 / cycles_per_sec); - fflush(stdout); + fflush(stderr); + printf( + "\n\ngpgpu_simulation_time = %u days, %u hrs, %u min, %u sec (%u sec)\n", + (unsigned)d, (unsigned)h, (unsigned)m, (unsigned)s, (unsigned)difference); + printf("gpgpu_simulation_rate = %u (inst/sec)\n", + (unsigned)(the_gpgpusim->g_the_gpu->gpu_tot_sim_insn / difference)); + const unsigned cycles_per_sec = + (unsigned)(the_gpgpusim->g_the_gpu->gpu_tot_sim_cycle / difference); + printf("gpgpu_simulation_rate = %u (cycle/sec)\n", cycles_per_sec); + printf("gpgpu_silicon_slowdown = %ux\n", + the_gpgpusim->g_the_gpu->shader_clock() * 1000 / cycles_per_sec); + fflush(stdout); } -int gpgpu_context::gpgpu_opencl_ptx_sim_main_perf( kernel_info_t *grid ) -{ - the_gpgpusim->g_the_gpu->launch(grid); - sem_post(&(the_gpgpusim->g_sim_signal_start)); - sem_wait(&(the_gpgpusim->g_sim_signal_finish)); - return 0; +int gpgpu_context::gpgpu_opencl_ptx_sim_main_perf(kernel_info_t *grid) { + the_gpgpusim->g_the_gpu->launch(grid); + sem_post(&(the_gpgpusim->g_sim_signal_start)); + sem_wait(&(the_gpgpusim->g_sim_signal_finish)); + return 0; } //! Functional simulation of OpenCL /*! * This function call the CUDA PTX functional simulator */ -int cuda_sim::gpgpu_opencl_ptx_sim_main_func( kernel_info_t *grid ) -{ - //calling the CUDA PTX simulator, sending the kernel by reference and a flag set to true, - //the flag used by the function to distinguish OpenCL calls from the CUDA simulation calls which - //it is needed by the called function to not register the exit the exit of OpenCL kernel as it doesn't register entering in the first place as the CUDA kernels does - gpgpu_cuda_ptx_sim_main_func( *grid, true ); - return 0; +int cuda_sim::gpgpu_opencl_ptx_sim_main_func(kernel_info_t *grid) { + // calling the CUDA PTX simulator, sending the kernel by reference and a flag + // set to true, + // the flag used by the function to distinguish OpenCL calls from the CUDA + // simulation calls which + // it is needed by the called function to not register the exit the exit of + // OpenCL kernel as it doesn't register entering in the first place as the + // CUDA kernels does + gpgpu_cuda_ptx_sim_main_func(*grid, true); + return 0; } diff --git a/src/gpgpusim_entrypoint.h b/src/gpgpusim_entrypoint.h index 9f408df..517885c 100644 --- a/src/gpgpusim_entrypoint.h +++ b/src/gpgpusim_entrypoint.h @@ -7,14 +7,16 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this +// Redistributions in binary form must reproduce the above copyright notice, +// this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -28,52 +30,50 @@ #ifndef GPGPUSIM_ENTRYPOINT_H_INCLUDED #define GPGPUSIM_ENTRYPOINT_H_INCLUDED -#include "abstract_hardware_model.h" #include <pthread.h> #include <semaphore.h> #include <time.h> +#include "abstract_hardware_model.h" -//extern time_t g_simulation_starttime; +// extern time_t g_simulation_starttime; class gpgpu_context; class GPGPUsim_ctx { - public: - GPGPUsim_ctx(gpgpu_context* ctx) { - g_sim_active = false; - g_sim_done = true; - break_limit = false; - g_sim_lock = PTHREAD_MUTEX_INITIALIZER; - - g_the_gpu_config=NULL; - g_the_gpu=NULL; - g_stream_manager=NULL; - the_cude_device=NULL; - the_context=NULL; - gpgpu_ctx = ctx; - } - - //struct gpgpu_ptx_sim_arg *grid_params; + public: + GPGPUsim_ctx(gpgpu_context *ctx) { + g_sim_active = false; + g_sim_done = true; + break_limit = false; + g_sim_lock = PTHREAD_MUTEX_INITIALIZER; - sem_t g_sim_signal_start; - sem_t g_sim_signal_finish; - sem_t g_sim_signal_exit; - time_t g_simulation_starttime; - pthread_t g_simulation_thread; + g_the_gpu_config = NULL; + g_the_gpu = NULL; + g_stream_manager = NULL; + the_cude_device = NULL; + the_context = NULL; + gpgpu_ctx = ctx; + } - class gpgpu_sim_config *g_the_gpu_config; - class gpgpu_sim *g_the_gpu; - class stream_manager *g_stream_manager; + // struct gpgpu_ptx_sim_arg *grid_params; - struct _cuda_device_id *the_cude_device; - struct CUctx_st* the_context; - gpgpu_context* gpgpu_ctx; + sem_t g_sim_signal_start; + sem_t g_sim_signal_finish; + sem_t g_sim_signal_exit; + time_t g_simulation_starttime; + pthread_t g_simulation_thread; + class gpgpu_sim_config *g_the_gpu_config; + class gpgpu_sim *g_the_gpu; + class stream_manager *g_stream_manager; - pthread_mutex_t g_sim_lock; - bool g_sim_active; - bool g_sim_done; - bool break_limit; + struct _cuda_device_id *the_cude_device; + struct CUctx_st *the_context; + gpgpu_context *gpgpu_ctx; + pthread_mutex_t g_sim_lock; + bool g_sim_active; + bool g_sim_done; + bool break_limit; }; #endif diff --git a/src/option_parser.cc b/src/option_parser.cc index 7d747f0..511553d 100644 --- a/src/option_parser.cc +++ b/src/option_parser.cc @@ -7,14 +7,16 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this +// Redistributions in binary form must reproduce the above copyright notice, +// this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -25,523 +27,527 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include "option_parser.h" +#include <assert.h> #include <stdio.h> #include <stdlib.h> -#include <assert.h> -#include <string> -#include <iostream> -#include <iomanip> -#include <sstream> +#include <string.h> #include <fstream> -#include <vector> +#include <iomanip> +#include <iostream> #include <list> #include <map> -#include <string.h> -#include "option_parser.h" - +#include <sstream> +#include <string> +#include <vector> using namespace std; // A generic option registry regardless of data type -class OptionRegistryInterface -{ -public: - OptionRegistryInterface(const string optionName, const string optionDesc) - : m_optionName(optionName), m_optionDesc(optionDesc), m_isParsed(false) - {} +class OptionRegistryInterface { + public: + OptionRegistryInterface(const string optionName, const string optionDesc) + : m_optionName(optionName), m_optionDesc(optionDesc), m_isParsed(false) {} - virtual ~OptionRegistryInterface() {} + virtual ~OptionRegistryInterface() {} - const string& GetName() { return m_optionName; } - const string& GetDesc() { return m_optionDesc; } - const bool isParsed() { return m_isParsed; } - virtual string toString() = 0; - virtual bool fromString(const string str) = 0; - virtual bool isFlag() = 0; - virtual bool assignDefault(const char *str) = 0; + const string &GetName() { return m_optionName; } + const string &GetDesc() { return m_optionDesc; } + const bool isParsed() { return m_isParsed; } + virtual string toString() = 0; + virtual bool fromString(const string str) = 0; + virtual bool isFlag() = 0; + virtual bool assignDefault(const char *str) = 0; -protected: - string m_optionName; - string m_optionDesc; - bool m_isParsed; // true if the target variable has been updated by fromString() + protected: + string m_optionName; + string m_optionDesc; + bool m_isParsed; // true if the target variable has been updated by + // fromString() }; // Template for option registry - class T = specify data type of the option template <class T> -class OptionRegistry : public OptionRegistryInterface -{ -public: - OptionRegistry(const string name, const string desc, T &variable) - : OptionRegistryInterface(name, desc), m_variable(variable) - {} +class OptionRegistry : public OptionRegistryInterface { + public: + OptionRegistry(const string name, const string desc, T &variable) + : OptionRegistryInterface(name, desc), m_variable(variable) {} - virtual ~OptionRegistry() {} + virtual ~OptionRegistry() {} - virtual string toString() - { - stringstream ss; - ss << m_variable; - return ss.str(); - } + virtual string toString() { + stringstream ss; + ss << m_variable; + return ss.str(); + } - virtual bool fromString(const string str) - { - stringstream ss(str); - ss.exceptions(stringstream::failbit | stringstream::badbit); - ss << setbase(10); - if (str.size() > 1 && str[0] == '0') { - if (str.size() > 2 && str[1] == 'x') { - ss.ignore(2); - ss << setbase(16); - } else { - ss.ignore(1); - ss << setbase(8); - } - } - try { - ss >> m_variable; - } catch (exception &e) { - return false; + virtual bool fromString(const string str) { + stringstream ss(str); + ss.exceptions(stringstream::failbit | stringstream::badbit); + ss << setbase(10); + if (str.size() > 1 && str[0] == '0') { + if (str.size() > 2 && str[1] == 'x') { + ss.ignore(2); + ss << setbase(16); + } else { + ss.ignore(1); + ss << setbase(8); } - m_isParsed = true; - return true; - } + } + try { + ss >> m_variable; + } catch (exception &e) { + return false; + } + m_isParsed = true; + return true; + } - virtual bool isFlag() { return false; } - virtual bool assignDefault(const char *str) { return fromString(str); } + virtual bool isFlag() { return false; } + virtual bool assignDefault(const char *str) { return fromString(str); } - operator T() - { - return m_variable; - } + operator T() { return m_variable; } -private: - T &m_variable; + private: + T &m_variable; }; // specialized parser for string-type options -template<> -bool OptionRegistry<string>::fromString(const string str) -{ - m_variable = str; - m_isParsed = true; - return true; +template <> +bool OptionRegistry<string>::fromString(const string str) { + m_variable = str; + m_isParsed = true; + return true; } // specialized parser for c-string type options -template<> -bool OptionRegistry<char *>::fromString(const string str) -{ - m_variable = new char[str.size() + 1]; - strcpy(m_variable, str.c_str()); - m_isParsed = true; - return true; +template <> +bool OptionRegistry<char *>::fromString(const string str) { + m_variable = new char[str.size() + 1]; + strcpy(m_variable, str.c_str()); + m_isParsed = true; + return true; } // specialized default assignment for c-string type option to allow NULL default -template<> -bool OptionRegistry<char *>::assignDefault(const char *str) -{ - m_variable = const_cast<char *>(str); // c-string options are not meant to be edited anyway - m_isParsed = true; - return true; +template <> +bool OptionRegistry<char *>::assignDefault(const char *str) { + m_variable = const_cast<char *>( + str); // c-string options are not meant to be edited anyway + m_isParsed = true; + return true; } // specialized default assignment for c-string type option to allow NULL default -template<> -string OptionRegistry<char *>::toString() -{ - stringstream ss; - if (m_variable != NULL) { - ss << m_variable; - } else { - ss << "NULL"; - } - return ss.str(); +template <> +string OptionRegistry<char *>::toString() { + stringstream ss; + if (m_variable != NULL) { + ss << m_variable; + } else { + ss << "NULL"; + } + return ss.str(); } -// specialized parser for boolean options -template<> -bool OptionRegistry<bool>::fromString(const string str) -{ - int value = 1; - bool parsed = true; - stringstream ss(str); - ss.exceptions(stringstream::failbit | stringstream::badbit); - try { - ss >> value; - } catch (stringstream::failure &ep) { - parsed = false; - } - assert(value == 0 or value == 1); // sanity check for boolean options (it can only be 1 or 0) - m_variable = (value != 0); - m_isParsed = true; - return parsed; +// specialized parser for boolean options +template <> +bool OptionRegistry<bool>::fromString(const string str) { + int value = 1; + bool parsed = true; + stringstream ss(str); + ss.exceptions(stringstream::failbit | stringstream::badbit); + try { + ss >> value; + } catch (stringstream::failure &ep) { + parsed = false; + } + assert(value == 0 or + value == + 1); // sanity check for boolean options (it can only be 1 or 0) + m_variable = (value != 0); + m_isParsed = true; + return parsed; } // specializing a flag query function to identify boolean option -template<> -bool OptionRegistry<bool>::isFlag() { return true; } - -// class holding a collection of options and parse them from command line/configfile -class OptionParser -{ -public: - OptionParser() {} - ~OptionParser() - { - OptionCollection::iterator i_option; - for (i_option = m_optionReg.begin(); i_option != m_optionReg.end(); ++i_option) { - delete (*i_option); - } - } +template <> +bool OptionRegistry<bool>::isFlag() { + return true; +} - template<class T> - void Register(const string optionName, const string optionDesc, T &optionVariable, const char *optionDefault) - { - OptionRegistry<T> *p_option = new OptionRegistry<T>(optionName, optionDesc, optionVariable); - m_optionReg.push_back(p_option); - m_optionMap[optionName] = p_option; - p_option->assignDefault(optionDefault); - } +// class holding a collection of options and parse them from command +// line/configfile +class OptionParser { + public: + OptionParser() {} + ~OptionParser() { + OptionCollection::iterator i_option; + for (i_option = m_optionReg.begin(); i_option != m_optionReg.end(); + ++i_option) { + delete (*i_option); + } + } - void ParseCommandLine(int argc, const char * const argv[]) - { - for (int i = 1; i < argc; i++) { - OptionMap::iterator i_option; - bool optionFound = false; + template <class T> + void Register(const string optionName, const string optionDesc, + T &optionVariable, const char *optionDefault) { + OptionRegistry<T> *p_option = + new OptionRegistry<T>(optionName, optionDesc, optionVariable); + m_optionReg.push_back(p_option); + m_optionMap[optionName] = p_option; + p_option->assignDefault(optionDefault); + } - i_option = m_optionMap.find(argv[i]); - if (i_option != m_optionMap.end()) { - const char *argstr = (i + 1 < argc)? argv[i + 1] : ""; - OptionRegistryInterface *p_option = i_option->second; - if (p_option->isFlag()) { - if (p_option->fromString(argstr) == true) { - i += 1; - } - } else { - if (p_option->fromString(argstr) == false) { - fprintf(stderr, "\n\nGPGPU-Sim ** ERROR: Cannot parse value '%s' for option '%s'.\n", argstr, argv[i]); - exit(1); - } - i += 1; - } - optionFound = true; - } else if (string(argv[i]) == "-config") { - if (i + 1 >= argc) { - fprintf(stderr, "\n\nGPGPU-Sim ** ERROR: Missing filename for option '-config'.\n"); - exit(1); - } + void ParseCommandLine(int argc, const char *const argv[]) { + for (int i = 1; i < argc; i++) { + OptionMap::iterator i_option; + bool optionFound = false; - ParseFile(argv[i + 1]); + i_option = m_optionMap.find(argv[i]); + if (i_option != m_optionMap.end()) { + const char *argstr = (i + 1 < argc) ? argv[i + 1] : ""; + OptionRegistryInterface *p_option = i_option->second; + if (p_option->isFlag()) { + if (p_option->fromString(argstr) == true) { i += 1; - optionFound = true; - } - if (optionFound == false) { - fprintf(stderr, "\n\nGPGPU-Sim ** ERROR: Unknown Option: '%s' \n", argv[i]); + } + } else { + if (p_option->fromString(argstr) == false) { + fprintf(stderr, + "\n\nGPGPU-Sim ** ERROR: Cannot parse value '%s' for " + "option '%s'.\n", + argstr, argv[i]); exit(1); - } - } - } - - - void ParseFile(const char *filename) { - ifstream inputFile; - stringstream args; + } + i += 1; + } + optionFound = true; + } else if (string(argv[i]) == "-config") { + if (i + 1 >= argc) { + fprintf(stderr, + "\n\nGPGPU-Sim ** ERROR: Missing filename for option " + "'-config'.\n"); + exit(1); + } - // open config file, stream every line into a continuous buffer - // get rid of comments in the process - inputFile.open(filename); - if (!inputFile.good()) { - fprintf(stderr, "\n\nGPGPU-Sim ** ERROR: Cannot open config file '%s'\n", filename); - exit(1); + ParseFile(argv[i + 1]); + i += 1; + optionFound = true; } - while (inputFile.good()) { - string line; - getline(inputFile, line); - size_t commentStart = line.find_first_of("#"); - if (commentStart != line.npos) { - line.erase(commentStart); - } - args << line << ' '; + if (optionFound == false) { + fprintf(stderr, "\n\nGPGPU-Sim ** ERROR: Unknown Option: '%s' \n", + argv[i]); + exit(1); } - inputFile.close(); + } + } - ParseStringStream(args); - } + void ParseFile(const char *filename) { + ifstream inputFile; + stringstream args; - // parse the given string as tokens separated by a set of given delimiters - void ParseString(string inputString, const string delimiters = string(" ;")) { - // convert all delimiter characters into whitespaces - for (unsigned t = 0; t < inputString.size(); t++) { - for (unsigned d = 0; d < delimiters.size(); d++) { - if (inputString[t] == delimiters.at(d)) { - inputString[t] = ' '; - break; - } - } + // open config file, stream every line into a continuous buffer + // get rid of comments in the process + inputFile.open(filename); + if (!inputFile.good()) { + fprintf(stderr, "\n\nGPGPU-Sim ** ERROR: Cannot open config file '%s'\n", + filename); + exit(1); + } + while (inputFile.good()) { + string line; + getline(inputFile, line); + size_t commentStart = line.find_first_of("#"); + if (commentStart != line.npos) { + line.erase(commentStart); } - stringstream args(inputString); - ParseStringStream(args); - } + args << line << ' '; + } + inputFile.close(); - // parse the given stringstream as whitespace-separated tokens. drain the stream in the process - void ParseStringStream(stringstream &args) { - // extract non-whitespace string tokens - vector<char*> argv; - argv.push_back(new char[6]); - strcpy(argv[0], "dummy"); - while (args.good()) { - string argNew; - args >> argNew; + ParseStringStream(args); + } - if (argNew.size() == 0) continue; // this is probably the last token + // parse the given string as tokens separated by a set of given delimiters + void ParseString(string inputString, const string delimiters = string(" ;")) { + // convert all delimiter characters into whitespaces + for (unsigned t = 0; t < inputString.size(); t++) { + for (unsigned d = 0; d < delimiters.size(); d++) { + if (inputString[t] == delimiters.at(d)) { + inputString[t] = ' '; + break; + } + } + } + stringstream args(inputString); + ParseStringStream(args); + } - if (argNew[0] == '"') { - while (args.good() && argNew[argNew.size()-1] != '"') { - string argCont; - args >> argCont; - argNew += " " + argCont; - } - argNew.erase(0,1); - argNew.erase(argNew.size()-1); - } + // parse the given stringstream as whitespace-separated tokens. drain the + // stream in the process + void ParseStringStream(stringstream &args) { + // extract non-whitespace string tokens + vector<char *> argv; + argv.push_back(new char[6]); + strcpy(argv[0], "dummy"); + while (args.good()) { + string argNew; + args >> argNew; - char *c_argNew = new char[argNew.size() + 1]; - strcpy(c_argNew, argNew.c_str()); - argv.push_back(c_argNew); - } + if (argNew.size() == 0) continue; // this is probably the last token - // pass the string token into normal commandline parser - char **targv = (char**)calloc(argv.size(), sizeof(char*)); - for( unsigned k=0; k < argv.size(); k++ ) - targv[k] = argv[k]; - ParseCommandLine(argv.size(), targv); - free(targv); - for (size_t i = 0; i < argv.size(); i++) { - delete[] argv[i]; + if (argNew[0] == '"') { + while (args.good() && argNew[argNew.size() - 1] != '"') { + string argCont; + args >> argCont; + argNew += " " + argCont; + } + argNew.erase(0, 1); + argNew.erase(argNew.size() - 1); } - } - void Print(FILE *fout) - { - OptionCollection::iterator i_option; - for (i_option = m_optionReg.begin(); i_option != m_optionReg.end(); ++i_option) { - stringstream sout; - if ((*i_option)->isParsed() == false) { - cerr << "\n\nGPGPU-Sim ** ERROR: Missing option '" << (*i_option)->GetName() << "'\n"; - assert(0); - } - sout << setw(20) << left << (*i_option)->GetName() << " "; - sout << setw(20) << right << (*i_option)->toString() << " # "; - sout << left << (*i_option)->GetDesc(); - sout << std::endl; - fprintf(fout, "%s", sout.str().c_str()); + char *c_argNew = new char[argNew.size() + 1]; + strcpy(c_argNew, argNew.c_str()); + argv.push_back(c_argNew); + } + + // pass the string token into normal commandline parser + char **targv = (char **)calloc(argv.size(), sizeof(char *)); + for (unsigned k = 0; k < argv.size(); k++) targv[k] = argv[k]; + ParseCommandLine(argv.size(), targv); + free(targv); + for (size_t i = 0; i < argv.size(); i++) { + delete[] argv[i]; + } + } + + void Print(FILE *fout) { + OptionCollection::iterator i_option; + for (i_option = m_optionReg.begin(); i_option != m_optionReg.end(); + ++i_option) { + stringstream sout; + if ((*i_option)->isParsed() == false) { + cerr << "\n\nGPGPU-Sim ** ERROR: Missing option '" + << (*i_option)->GetName() << "'\n"; + assert(0); } - } + sout << setw(20) << left << (*i_option)->GetName() << " "; + sout << setw(20) << right << (*i_option)->toString() << " # "; + sout << left << (*i_option)->GetDesc(); + sout << std::endl; + fprintf(fout, "%s", sout.str().c_str()); + } + } -private: - typedef list<OptionRegistryInterface*> OptionCollection; - OptionCollection m_optionReg; - typedef map<string, OptionRegistryInterface*> OptionMap; - OptionMap m_optionMap; + private: + typedef list<OptionRegistryInterface *> OptionCollection; + OptionCollection m_optionReg; + typedef map<string, OptionRegistryInterface *> OptionMap; + OptionMap m_optionMap; }; #include "option_parser.h" -option_parser_t option_parser_create() -{ - OptionParser *p_opr = new OptionParser(); - return reinterpret_cast<option_parser_t>(p_opr); +option_parser_t option_parser_create() { + OptionParser *p_opr = new OptionParser(); + return reinterpret_cast<option_parser_t>(p_opr); } -void option_parser_destroy(option_parser_t opp) -{ - OptionParser *p_opr = reinterpret_cast<OptionParser *>(opp); - delete p_opr; +void option_parser_destroy(option_parser_t opp) { + OptionParser *p_opr = reinterpret_cast<OptionParser *>(opp); + delete p_opr; } -void option_parser_register(option_parser_t opp, - const char *name, - enum option_dtype type, - void *variable, - const char *desc, - const char *defaultvalue) -{ - OptionParser *p_opr = reinterpret_cast<OptionParser *>(opp); - switch (type) { - case OPT_INT32: p_opr->Register<int>(name, desc, *(int*)variable, defaultvalue); break; - case OPT_UINT32: p_opr->Register<unsigned int>(name, desc, *(unsigned int*)variable, defaultvalue); break; - case OPT_INT64: p_opr->Register<long long>(name, desc, *(long long*)variable, defaultvalue); break; - case OPT_UINT64: p_opr->Register<unsigned long long>(name, desc, *(unsigned long long*)variable, defaultvalue); break; - case OPT_BOOL: p_opr->Register<bool>(name, desc, *(bool*)variable, defaultvalue); break; - case OPT_FLOAT: p_opr->Register<float>(name, desc, *(float*)variable, defaultvalue); break; - case OPT_DOUBLE: p_opr->Register<double>(name, desc, *(double*)variable, defaultvalue); break; - case OPT_CHAR: p_opr->Register<char>(name, desc, *(char*)variable, defaultvalue); break; - case OPT_CSTR: p_opr->Register<char*>(name, desc, *(char**)variable, defaultvalue); break; - default: - fprintf(stderr, "\n\nGPGPU-Sim ** ERROR: option data type (%d) not supported!\n", type); - exit(1); - break; - } +void option_parser_register(option_parser_t opp, const char *name, + enum option_dtype type, void *variable, + const char *desc, const char *defaultvalue) { + OptionParser *p_opr = reinterpret_cast<OptionParser *>(opp); + switch (type) { + case OPT_INT32: + p_opr->Register<int>(name, desc, *(int *)variable, defaultvalue); + break; + case OPT_UINT32: + p_opr->Register<unsigned int>(name, desc, *(unsigned int *)variable, + defaultvalue); + break; + case OPT_INT64: + p_opr->Register<long long>(name, desc, *(long long *)variable, + defaultvalue); + break; + case OPT_UINT64: + p_opr->Register<unsigned long long>( + name, desc, *(unsigned long long *)variable, defaultvalue); + break; + case OPT_BOOL: + p_opr->Register<bool>(name, desc, *(bool *)variable, defaultvalue); + break; + case OPT_FLOAT: + p_opr->Register<float>(name, desc, *(float *)variable, defaultvalue); + break; + case OPT_DOUBLE: + p_opr->Register<double>(name, desc, *(double *)variable, defaultvalue); + break; + case OPT_CHAR: + p_opr->Register<char>(name, desc, *(char *)variable, defaultvalue); + break; + case OPT_CSTR: + p_opr->Register<char *>(name, desc, *(char **)variable, defaultvalue); + break; + default: + fprintf(stderr, + "\n\nGPGPU-Sim ** ERROR: option data type (%d) not supported!\n", + type); + exit(1); + break; + } } -void option_parser_cmdline(option_parser_t opp, - int argc, const char *argv[]) -{ - OptionParser *p_opr = reinterpret_cast<OptionParser *>(opp); - return p_opr->ParseCommandLine(argc,argv); - +void option_parser_cmdline(option_parser_t opp, int argc, const char *argv[]) { + OptionParser *p_opr = reinterpret_cast<OptionParser *>(opp); + return p_opr->ParseCommandLine(argc, argv); } - -void option_parser_cfgfile(option_parser_t opp, - const char *filename) -{ - OptionParser *p_opr = reinterpret_cast<OptionParser *>(opp); - p_opr->ParseFile(filename); +void option_parser_cfgfile(option_parser_t opp, const char *filename) { + OptionParser *p_opr = reinterpret_cast<OptionParser *>(opp); + p_opr->ParseFile(filename); } void option_parser_delimited_string(option_parser_t opp, - const char *inputstring, - const char *delimiters) -{ - OptionParser *p_opr = reinterpret_cast<OptionParser *>(opp); - p_opr->ParseString(inputstring, delimiters); + const char *inputstring, + const char *delimiters) { + OptionParser *p_opr = reinterpret_cast<OptionParser *>(opp); + p_opr->ParseString(inputstring, delimiters); } -void option_parser_print(option_parser_t opp, - FILE *fout) -{ - OptionParser *p_opr = reinterpret_cast<OptionParser *>(opp); - p_opr->Print(fout); +void option_parser_print(option_parser_t opp, FILE *fout) { + OptionParser *p_opr = reinterpret_cast<OptionParser *>(opp); + p_opr->Print(fout); } - - // #define UNIT_TEST #ifdef UNIT_TEST -class testtype -{ -public: - int idata; - float fdata; - string sdata; - unsigned long long ulldata; - bool bdata; - unsigned int boolint; - char * coption; +class testtype { + public: + int idata; + float fdata; + string sdata; + unsigned long long ulldata; + bool bdata; + unsigned int boolint; + char *coption; - testtype() - : idata(0), - fdata(0.0f), - sdata(""), - ulldata(0), - bdata(false) - { } + testtype() : idata(0), fdata(0.0f), sdata(""), ulldata(0), bdata(false) {} }; +int cppinterfacetest(int argc, const char *argv[]) { + testtype c; + OptionParser optionparser; + c.idata = 123; + c.fdata = 3249586.333; + c.sdata = string("haha"); -int cppinterfacetest(int argc, const char *argv[]) -{ - testtype c; - OptionParser optionparser; - c.idata = 123; - c.fdata = 3249586.333; - c.sdata = string("haha"); - - optionparser.Register<int>("-idata", "integer data", c.idata, "-456"); - optionparser.Register<float>("-fdata", "floating point data", c.fdata, "0.001"); - optionparser.Register<string>("-sdata", "first string data", c.sdata, "hellow"); - optionparser.Register<unsigned long long>("-ulldata", "unsigned long long data", c.ulldata, "0x123456789abcdef1"); - optionparser.Register<bool>("-someflag", "first flag", c.bdata, "0"); - optionparser.Register<bool>("-otherflag", "second flag", (bool&)c.boolint, "1"); - optionparser.Register<char *>("-coption", "char * data", c.coption, NULL); + optionparser.Register<int>("-idata", "integer data", c.idata, "-456"); + optionparser.Register<float>("-fdata", "floating point data", c.fdata, + "0.001"); + optionparser.Register<string>("-sdata", "first string data", c.sdata, + "hellow"); + optionparser.Register<unsigned long long>( + "-ulldata", "unsigned long long data", c.ulldata, "0x123456789abcdef1"); + optionparser.Register<bool>("-someflag", "first flag", c.bdata, "0"); + optionparser.Register<bool>("-otherflag", "second flag", (bool &)c.boolint, + "1"); + optionparser.Register<char *>("-coption", "char * data", c.coption, NULL); - cout << "Default: \n"; - optionparser.Print(stdout); + cout << "Default: \n"; + optionparser.Print(stdout); - optionparser.ParseCommandLine(argc, argv); + optionparser.ParseCommandLine(argc, argv); - cout << "Commandline Parse Results: \n"; - optionparser.Print(stdout); + cout << "Commandline Parse Results: \n"; + optionparser.Print(stdout); - optionparser.ParseFile("test.config"); - cout << "File Parse Results: \n"; - optionparser.Print(stdout); - cout << c.sdata << ' ' << c.idata << endl; + optionparser.ParseFile("test.config"); + cout << "File Parse Results: \n"; + optionparser.Print(stdout); + cout << c.sdata << ' ' << c.idata << endl; - return 0; + return 0; } -int cinterfacetest(int argc, const char *argv[]) -{ - testtype c; - option_parser_t opp = option_parser_create(); - c.idata = 123; - c.fdata = 3249586.333; - c.sdata = string("haha"); - char *otherstr; +int cinterfacetest(int argc, const char *argv[]) { + testtype c; + option_parser_t opp = option_parser_create(); + c.idata = 123; + c.fdata = 3249586.333; + c.sdata = string("haha"); + char *otherstr; - option_parser_register(opp, "-idata", OPT_INT32, &c.idata, "integer data", "-456"); - option_parser_register(opp, "-fdata", OPT_FLOAT, &c.fdata, "floating point data", "0.001"); - option_parser_register(opp, "-sdata", OPT_CSTR, &otherstr, "first string data", "hellow"); - option_parser_register(opp, "-ulldata", OPT_UINT64, &c.ulldata, "unsigend long long data", "0x123456789abcdef1"); - option_parser_register(opp, "-someflag", OPT_BOOL, &c.bdata, "first flag", "0"); - option_parser_register(opp, "-otherflag", OPT_BOOL, &c.boolint, "second flag", "1"); - option_parser_register(opp, "-coption", OPT_CSTR, &c.coption, "char * data", NULL); + option_parser_register(opp, "-idata", OPT_INT32, &c.idata, "integer data", + "-456"); + option_parser_register(opp, "-fdata", OPT_FLOAT, &c.fdata, + "floating point data", "0.001"); + option_parser_register(opp, "-sdata", OPT_CSTR, &otherstr, + "first string data", "hellow"); + option_parser_register(opp, "-ulldata", OPT_UINT64, &c.ulldata, + "unsigend long long data", "0x123456789abcdef1"); + option_parser_register(opp, "-someflag", OPT_BOOL, &c.bdata, "first flag", + "0"); + option_parser_register(opp, "-otherflag", OPT_BOOL, &c.boolint, "second flag", + "1"); + option_parser_register(opp, "-coption", OPT_CSTR, &c.coption, "char * data", + NULL); - printf("Default: \n"); - option_parser_print(opp, stdout); + printf("Default: \n"); + option_parser_print(opp, stdout); - option_parser_cmdline(opp, argc, argv); + option_parser_cmdline(opp, argc, argv); - printf("Commandline Parse Results: \n"); - option_parser_print(opp, stdout); + printf("Commandline Parse Results: \n"); + option_parser_print(opp, stdout); - option_parser_cfgfile(opp, "test.config"); - printf("File Parse Results: \n"); - option_parser_print(opp, stdout); - printf("%s %d\n", otherstr, c.idata); + option_parser_cfgfile(opp, "test.config"); + printf("File Parse Results: \n"); + option_parser_print(opp, stdout); + printf("%s %d\n", otherstr, c.idata); - option_parser_destroy(opp); + option_parser_destroy(opp); - return 0; + return 0; } -int stringparsertest() -{ - int tABC; - int tDEF; - char tMode; - char *tName; +int stringparsertest() { + int tABC; + int tDEF; + char tMode; + char *tName; - option_parser_t opp = option_parser_create(); - option_parser_register(opp, "ABC", OPT_INT32, &tABC, "tABC", "34"); - option_parser_register(opp, "DEF", OPT_INT32, &tDEF, "tDEF", "-56"); - option_parser_register(opp, "Mode", OPT_CHAR, &tMode, "tMode", "P"); - option_parser_register(opp, "Name", OPT_CSTR, &tName, "tName", "Cache"); + option_parser_t opp = option_parser_create(); + option_parser_register(opp, "ABC", OPT_INT32, &tABC, "tABC", "34"); + option_parser_register(opp, "DEF", OPT_INT32, &tDEF, "tDEF", "-56"); + option_parser_register(opp, "Mode", OPT_CHAR, &tMode, "tMode", "P"); + option_parser_register(opp, "Name", OPT_CSTR, &tName, "tName", "Cache"); - option_parser_delimited_string(opp, "ABC 1111; DEF 88; Mode A; Name out", " ;"); - printf("String Parse Results: \n"); - option_parser_print(opp, stdout); + option_parser_delimited_string(opp, "ABC 1111; DEF 88; Mode A; Name out", + " ;"); + printf("String Parse Results: \n"); + option_parser_print(opp, stdout); - option_parser_delimited_string(opp, "Name=dram;DEF=702;Mode=B;ABC=-9573;", " =;"); - printf("String Parse Results: \n"); - option_parser_print(opp, stdout); + option_parser_delimited_string(opp, "Name=dram;DEF=702;Mode=B;ABC=-9573;", + " =;"); + printf("String Parse Results: \n"); + option_parser_print(opp, stdout); - return 0; + return 0; } -int main(int argc, const char *argv[]) -{ - cppinterfacetest(argc,argv); - cinterfacetest(argc,argv); - stringparsertest(); +int main(int argc, const char *argv[]) { + cppinterfacetest(argc, argv); + cinterfacetest(argc, argv); + stringparsertest(); - return 0; + return 0; } #endif - diff --git a/src/option_parser.h b/src/option_parser.h index 1f7f96c..180bc9d 100644 --- a/src/option_parser.h +++ b/src/option_parser.h @@ -7,14 +7,16 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this +// Redistributions in binary form must reproduce the above copyright notice, +// this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -25,26 +27,25 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#pragma once +#pragma once #include <stdio.h> #include <stdlib.h> - // pointer to C++ class typedef class OptionParser *option_parser_t; // data type of the option enum option_dtype { - OPT_INT32, - OPT_UINT32, - OPT_INT64, - OPT_UINT64, - OPT_BOOL, - OPT_FLOAT, - OPT_DOUBLE, - OPT_CHAR, - OPT_CSTR + OPT_INT32, + OPT_UINT32, + OPT_INT64, + OPT_UINT64, + OPT_BOOL, + OPT_FLOAT, + OPT_DOUBLE, + OPT_CHAR, + OPT_CSTR }; // create and destroy option parser @@ -52,28 +53,19 @@ option_parser_t option_parser_create(); void option_parser_destroy(option_parser_t opp); // register new option -void option_parser_register(option_parser_t opp, - const char *name, - enum option_dtype type, - void *variable, - const char *desc, - const char *defaultvalue); +void option_parser_register(option_parser_t opp, const char *name, + enum option_dtype type, void *variable, + const char *desc, const char *defaultvalue); // parse command line -void option_parser_cmdline(option_parser_t opp, - int argc, const char *argv[]); - - +void option_parser_cmdline(option_parser_t opp, int argc, const char *argv[]); // parse config file -void option_parser_cfgfile(option_parser_t opp, - const char *filename); +void option_parser_cfgfile(option_parser_t opp, const char *filename); // parse a delimited string void option_parser_delimited_string(option_parser_t opp, - const char *inputstring, + const char *inputstring, const char *delimiters); // print options -void option_parser_print(option_parser_t opp, - FILE *fout); - +void option_parser_print(option_parser_t opp, FILE *fout); diff --git a/src/statwrapper.cc b/src/statwrapper.cc index e273e78..cda25b6 100644 --- a/src/statwrapper.cc +++ b/src/statwrapper.cc @@ -1,48 +1,33 @@ -//a Wraper function for stats class -#include "intersim2/stats.hpp" +// a Wraper function for stats class #include <stdio.h> +#include "intersim2/stats.hpp" -Stats* StatCreate (const char * name, double bin_size, int num_bins) { - Stats* newstat = new Stats(NULL,name,bin_size,num_bins); - newstat->Clear (); - return newstat; +Stats *StatCreate(const char *name, double bin_size, int num_bins) { + Stats *newstat = new Stats(NULL, name, bin_size, num_bins); + newstat->Clear(); + return newstat; } -void StatClear(void * st) -{ - ((Stats *)st)->Clear(); -} +void StatClear(void *st) { ((Stats *)st)->Clear(); } -void StatAddSample (void * st, int val) -{ - ((Stats *)st)->AddSample(val); -} +void StatAddSample(void *st, int val) { ((Stats *)st)->AddSample(val); } -double StatAverage(void * st) -{ - return((Stats *)st)->Average(); -} +double StatAverage(void *st) { return ((Stats *)st)->Average(); } -double StatMax(void * st) -{ - return((Stats *)st)->Max(); -} +double StatMax(void *st) { return ((Stats *)st)->Max(); } -double StatMin(void * st) -{ - return((Stats *)st)->Min(); -} +double StatMin(void *st) { return ((Stats *)st)->Min(); } -void StatDisp (void * st) -{ - printf ("Stats for "); - ((Stats *)st)->DisplayHierarchy(); -// if (((Stats *)st)->NeverUsed()) { -// printf (" was never updated!\n"); -// } else { - printf("Min %f Max %f Average %f \n",((Stats *)st)->Min(),((Stats *)st)->Max(),StatAverage(st)); - ((Stats *)st)->Display(); -// } +void StatDisp(void *st) { + printf("Stats for "); + ((Stats *)st)->DisplayHierarchy(); + // if (((Stats *)st)->NeverUsed()) { + // printf (" was never updated!\n"); + // } else { + printf("Min %f Max %f Average %f \n", ((Stats *)st)->Min(), + ((Stats *)st)->Max(), StatAverage(st)); + ((Stats *)st)->Display(); + // } } #if 0 @@ -55,5 +40,3 @@ int main () StatDisp(mytest); } #endif - - diff --git a/src/statwrapper.h b/src/statwrapper.h index 65c2ab9..4c00447 100644 --- a/src/statwrapper.h +++ b/src/statwrapper.h @@ -1,12 +1,12 @@ #ifndef STAT_WRAPER_H #define STAT_WRAPER_H -class Stats* StatCreate (const char * name, double bin_size, int num_bins) ; -void StatClear(void * st); -void StatAddSample (void * st, int val); -double StatAverage(void * st) ; -double StatMax(void * st) ; -double StatMin(void * st) ; -void StatDisp (void * st); +class Stats* StatCreate(const char* name, double bin_size, int num_bins); +void StatClear(void* st); +void StatAddSample(void* st, int val); +double StatAverage(void* st); +double StatMax(void* st); +double StatMin(void* st); +void StatDisp(void* st); #endif diff --git a/src/stream_manager.cc b/src/stream_manager.cc index be3dd71..f813ed4 100644 --- a/src/stream_manager.cc +++ b/src/stream_manager.cc @@ -7,14 +7,16 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this +// Redistributions in binary form must reproduce the above copyright notice, +// this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -26,463 +28,445 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "stream_manager.h" -#include "gpgpusim_entrypoint.h" +#include "../libcuda/gpgpu_context.h" #include "cuda-sim/cuda-sim.h" #include "gpgpu-sim/gpu-sim.h" -#include "../libcuda/gpgpu_context.h" +#include "gpgpusim_entrypoint.h" unsigned CUstream_st::sm_next_stream_uid = 0; -CUstream_st::CUstream_st() -{ - m_pending = false; - m_uid = sm_next_stream_uid++; - pthread_mutex_init(&m_lock,NULL); -} - -bool CUstream_st::empty() -{ - pthread_mutex_lock(&m_lock); - bool empty = m_operations.empty(); - pthread_mutex_unlock(&m_lock); - return empty; +CUstream_st::CUstream_st() { + m_pending = false; + m_uid = sm_next_stream_uid++; + pthread_mutex_init(&m_lock, NULL); } -bool CUstream_st::busy() -{ - pthread_mutex_lock(&m_lock); - bool pending = m_pending; - pthread_mutex_unlock(&m_lock); - return pending; +bool CUstream_st::empty() { + pthread_mutex_lock(&m_lock); + bool empty = m_operations.empty(); + pthread_mutex_unlock(&m_lock); + return empty; } -void CUstream_st::synchronize() -{ - // called by host thread - bool done=false; - do{ - pthread_mutex_lock(&m_lock); - done = m_operations.empty(); - pthread_mutex_unlock(&m_lock); - } while ( !done ); +bool CUstream_st::busy() { + pthread_mutex_lock(&m_lock); + bool pending = m_pending; + pthread_mutex_unlock(&m_lock); + return pending; } -void CUstream_st::push( const stream_operation &op ) -{ - // called by host thread +void CUstream_st::synchronize() { + // called by host thread + bool done = false; + do { pthread_mutex_lock(&m_lock); - m_operations.push_back( op ); + done = m_operations.empty(); pthread_mutex_unlock(&m_lock); + } while (!done); } -void CUstream_st::record_next_done() -{ - // called by gpu thread - pthread_mutex_lock(&m_lock); - assert(m_pending); - m_operations.pop_front(); - m_pending=false; - pthread_mutex_unlock(&m_lock); +void CUstream_st::push(const stream_operation &op) { + // called by host thread + pthread_mutex_lock(&m_lock); + m_operations.push_back(op); + pthread_mutex_unlock(&m_lock); } - -stream_operation CUstream_st::next() -{ - // called by gpu thread - pthread_mutex_lock(&m_lock); - m_pending = true; - stream_operation result = m_operations.front(); - pthread_mutex_unlock(&m_lock); - return result; +void CUstream_st::record_next_done() { + // called by gpu thread + pthread_mutex_lock(&m_lock); + assert(m_pending); + m_operations.pop_front(); + m_pending = false; + pthread_mutex_unlock(&m_lock); } -void CUstream_st::cancel_front() -{ - pthread_mutex_lock(&m_lock); - assert(m_pending); - m_pending = false; - pthread_mutex_unlock(&m_lock); - +stream_operation CUstream_st::next() { + // called by gpu thread + pthread_mutex_lock(&m_lock); + m_pending = true; + stream_operation result = m_operations.front(); + pthread_mutex_unlock(&m_lock); + return result; } -void CUstream_st::print(FILE *fp) -{ - pthread_mutex_lock(&m_lock); - fprintf(fp,"GPGPU-Sim API: stream %u has %zu operations\n", m_uid, m_operations.size() ); - std::list<stream_operation>::iterator i; - unsigned n=0; - for( i=m_operations.begin(); i!=m_operations.end(); i++ ) { - stream_operation &op = *i; - fprintf(fp,"GPGPU-Sim API: %u : ", n++); - op.print(fp); - fprintf(fp,"\n"); - } - pthread_mutex_unlock(&m_lock); +void CUstream_st::cancel_front() { + pthread_mutex_lock(&m_lock); + assert(m_pending); + m_pending = false; + pthread_mutex_unlock(&m_lock); } +void CUstream_st::print(FILE *fp) { + pthread_mutex_lock(&m_lock); + fprintf(fp, "GPGPU-Sim API: stream %u has %zu operations\n", m_uid, + m_operations.size()); + std::list<stream_operation>::iterator i; + unsigned n = 0; + for (i = m_operations.begin(); i != m_operations.end(); i++) { + stream_operation &op = *i; + fprintf(fp, "GPGPU-Sim API: %u : ", n++); + op.print(fp); + fprintf(fp, "\n"); + } + pthread_mutex_unlock(&m_lock); +} -bool stream_operation::do_operation( gpgpu_sim *gpu ) -{ - if( is_noop() ) - return true; +bool stream_operation::do_operation(gpgpu_sim *gpu) { + if (is_noop()) return true; - assert(!m_done && m_stream); - if(g_debug_execution >= 3) - printf("GPGPU-Sim API: stream %u performing ", m_stream->get_uid() ); - switch( m_type ) { + assert(!m_done && m_stream); + if (g_debug_execution >= 3) + printf("GPGPU-Sim API: stream %u performing ", m_stream->get_uid()); + switch (m_type) { case stream_memcpy_host_to_device: - if(g_debug_execution >= 3) - printf("memcpy host-to-device\n"); - gpu->memcpy_to_gpu(m_device_address_dst,m_host_address_src,m_cnt); - m_stream->record_next_done(); - break; + if (g_debug_execution >= 3) printf("memcpy host-to-device\n"); + gpu->memcpy_to_gpu(m_device_address_dst, m_host_address_src, m_cnt); + m_stream->record_next_done(); + break; case stream_memcpy_device_to_host: - if(g_debug_execution >= 3) - printf("memcpy device-to-host\n"); - gpu->memcpy_from_gpu(m_host_address_dst,m_device_address_src,m_cnt); - m_stream->record_next_done(); - break; + if (g_debug_execution >= 3) printf("memcpy device-to-host\n"); + gpu->memcpy_from_gpu(m_host_address_dst, m_device_address_src, m_cnt); + m_stream->record_next_done(); + break; case stream_memcpy_device_to_device: - if(g_debug_execution >= 3) - printf("memcpy device-to-device\n"); - gpu->memcpy_gpu_to_gpu(m_device_address_dst,m_device_address_src,m_cnt); - m_stream->record_next_done(); - break; + if (g_debug_execution >= 3) printf("memcpy device-to-device\n"); + gpu->memcpy_gpu_to_gpu(m_device_address_dst, m_device_address_src, m_cnt); + m_stream->record_next_done(); + break; case stream_memcpy_to_symbol: - if(g_debug_execution >= 3) - printf("memcpy to symbol\n"); - gpu->gpgpu_ctx->func_sim->gpgpu_ptx_sim_memcpy_symbol(m_symbol,m_host_address_src,m_cnt,m_offset,1,gpu); - m_stream->record_next_done(); - break; + if (g_debug_execution >= 3) printf("memcpy to symbol\n"); + gpu->gpgpu_ctx->func_sim->gpgpu_ptx_sim_memcpy_symbol( + m_symbol, m_host_address_src, m_cnt, m_offset, 1, gpu); + m_stream->record_next_done(); + break; case stream_memcpy_from_symbol: - if(g_debug_execution >= 3) - printf("memcpy from symbol\n"); - gpu->gpgpu_ctx->func_sim->gpgpu_ptx_sim_memcpy_symbol(m_symbol,m_host_address_dst,m_cnt,m_offset,0,gpu); - m_stream->record_next_done(); - break; + if (g_debug_execution >= 3) printf("memcpy from symbol\n"); + gpu->gpgpu_ctx->func_sim->gpgpu_ptx_sim_memcpy_symbol( + m_symbol, m_host_address_dst, m_cnt, m_offset, 0, gpu); + m_stream->record_next_done(); + break; case stream_kernel_launch: - if( m_sim_mode ) { //Functional Sim - if(g_debug_execution >= 3) { - printf("kernel %d: \'%s\' transfer to GPU hardware scheduler\n", m_kernel->get_uid(), m_kernel->name().c_str() ); - m_kernel->print_parent_info(); - } - gpu->set_cache_config(m_kernel->name()); - gpu->functional_launch( m_kernel ); + if (m_sim_mode) { // Functional Sim + if (g_debug_execution >= 3) { + printf("kernel %d: \'%s\' transfer to GPU hardware scheduler\n", + m_kernel->get_uid(), m_kernel->name().c_str()); + m_kernel->print_parent_info(); } - else { //Performance Sim - if( gpu->can_start_kernel() && m_kernel->m_launch_latency == 0) { - if(g_debug_execution >= 3) { - printf("kernel %d: \'%s\' transfer to GPU hardware scheduler\n", m_kernel->get_uid(), m_kernel->name().c_str() ); - m_kernel->print_parent_info(); - } - gpu->set_cache_config(m_kernel->name()); - gpu->launch( m_kernel ); - } - else { - if(m_kernel->m_launch_latency) - m_kernel->m_launch_latency--; - if(g_debug_execution >= 3) - printf("kernel %d: \'%s\', latency %u not ready to transfer to GPU hardware scheduler\n", - m_kernel->get_uid(), m_kernel->name().c_str(), m_kernel->m_launch_latency); - return false; - } + gpu->set_cache_config(m_kernel->name()); + gpu->functional_launch(m_kernel); + } else { // Performance Sim + if (gpu->can_start_kernel() && m_kernel->m_launch_latency == 0) { + if (g_debug_execution >= 3) { + printf("kernel %d: \'%s\' transfer to GPU hardware scheduler\n", + m_kernel->get_uid(), m_kernel->name().c_str()); + m_kernel->print_parent_info(); + } + gpu->set_cache_config(m_kernel->name()); + gpu->launch(m_kernel); + } else { + if (m_kernel->m_launch_latency) m_kernel->m_launch_latency--; + if (g_debug_execution >= 3) + printf( + "kernel %d: \'%s\', latency %u not ready to transfer to GPU " + "hardware scheduler\n", + m_kernel->get_uid(), m_kernel->name().c_str(), + m_kernel->m_launch_latency); + return false; } - break; + } + break; case stream_event: { - printf("event update\n"); - time_t wallclock = time((time_t *)NULL); - m_event->update( gpu->gpu_tot_sim_cycle, wallclock ); - m_stream->record_next_done(); - } - break; + printf("event update\n"); + time_t wallclock = time((time_t *)NULL); + m_event->update(gpu->gpu_tot_sim_cycle, wallclock); + m_stream->record_next_done(); + } break; case stream_wait_event: { - //only allows next op to go if event is done - //otherwise stays in the stream queue - printf("stream wait event processing...\n"); - if(m_event->done()) - printf("stream wait event done\n"); - m_stream->record_next_done(); - } - break; + // only allows next op to go if event is done + // otherwise stays in the stream queue + printf("stream wait event processing...\n"); + if (m_event->done()) printf("stream wait event done\n"); + m_stream->record_next_done(); + } break; default: - abort(); - } - m_done=true; - fflush(stdout); - return true; + abort(); + } + m_done = true; + fflush(stdout); + return true; } -void stream_operation::print( FILE *fp ) const -{ - fprintf(fp," stream operation " ); - switch( m_type ) { - case stream_event: fprintf(fp,"event"); break; - case stream_kernel_launch: fprintf(fp,"kernel"); break; - case stream_memcpy_device_to_device: fprintf(fp,"memcpy device-to-device"); break; - case stream_memcpy_device_to_host: fprintf(fp,"memcpy device-to-host"); break; - case stream_memcpy_host_to_device: fprintf(fp,"memcpy host-to-device"); break; - case stream_memcpy_to_symbol: fprintf(fp,"memcpy to symbol"); break; - case stream_memcpy_from_symbol: fprintf(fp,"memcpy from symbol"); break; - case stream_no_op: fprintf(fp,"no-op"); break; - } +void stream_operation::print(FILE *fp) const { + fprintf(fp, " stream operation "); + switch (m_type) { + case stream_event: + fprintf(fp, "event"); + break; + case stream_kernel_launch: + fprintf(fp, "kernel"); + break; + case stream_memcpy_device_to_device: + fprintf(fp, "memcpy device-to-device"); + break; + case stream_memcpy_device_to_host: + fprintf(fp, "memcpy device-to-host"); + break; + case stream_memcpy_host_to_device: + fprintf(fp, "memcpy host-to-device"); + break; + case stream_memcpy_to_symbol: + fprintf(fp, "memcpy to symbol"); + break; + case stream_memcpy_from_symbol: + fprintf(fp, "memcpy from symbol"); + break; + case stream_no_op: + fprintf(fp, "no-op"); + break; + } } -stream_manager::stream_manager( gpgpu_sim *gpu, bool cuda_launch_blocking ) -{ - m_gpu = gpu; - m_service_stream_zero = false; - m_cuda_launch_blocking = cuda_launch_blocking; - pthread_mutex_init(&m_lock,NULL); +stream_manager::stream_manager(gpgpu_sim *gpu, bool cuda_launch_blocking) { + m_gpu = gpu; + m_service_stream_zero = false; + m_cuda_launch_blocking = cuda_launch_blocking; + pthread_mutex_init(&m_lock, NULL); } -bool stream_manager::operation( bool * sim) -{ - bool check=check_finished_kernel(); - pthread_mutex_lock(&m_lock); -// if(check)m_gpu->print_stats(); - stream_operation op =front(); - if(!op.do_operation( m_gpu )) //not ready to execute - { - //cancel operation - if( op.is_kernel() ) { - unsigned grid_uid = op.get_kernel()->get_uid(); - m_grid_id_to_stream.erase(grid_uid); - } - op.get_stream()->cancel_front(); - +bool stream_manager::operation(bool *sim) { + bool check = check_finished_kernel(); + pthread_mutex_lock(&m_lock); + // if(check)m_gpu->print_stats(); + stream_operation op = front(); + if (!op.do_operation(m_gpu)) // not ready to execute + { + // cancel operation + if (op.is_kernel()) { + unsigned grid_uid = op.get_kernel()->get_uid(); + m_grid_id_to_stream.erase(grid_uid); } - pthread_mutex_unlock(&m_lock); - //pthread_mutex_lock(&m_lock); - // simulate a clock cycle on the GPU - return check; + op.get_stream()->cancel_front(); + } + pthread_mutex_unlock(&m_lock); + // pthread_mutex_lock(&m_lock); + // simulate a clock cycle on the GPU + return check; } -bool stream_manager::check_finished_kernel() -{ - unsigned grid_uid = m_gpu->finished_kernel(); - bool check=register_finished_kernel(grid_uid); - return check; +bool stream_manager::check_finished_kernel() { + unsigned grid_uid = m_gpu->finished_kernel(); + bool check = register_finished_kernel(grid_uid); + return check; } -bool stream_manager::register_finished_kernel(unsigned grid_uid) -{ - // called by gpu simulation thread - if(grid_uid > 0){ - CUstream_st *stream = m_grid_id_to_stream[grid_uid]; - kernel_info_t *kernel = stream->front().get_kernel(); - assert( grid_uid == kernel->get_uid() ); +bool stream_manager::register_finished_kernel(unsigned grid_uid) { + // called by gpu simulation thread + if (grid_uid > 0) { + CUstream_st *stream = m_grid_id_to_stream[grid_uid]; + kernel_info_t *kernel = stream->front().get_kernel(); + assert(grid_uid == kernel->get_uid()); - //Jin: should check children kernels for CDP - if(kernel->is_finished()) { -// std::ofstream kernel_stat("kernel_stat.txt", std::ofstream::out | std::ofstream::app); -// kernel_stat<< " kernel " << grid_uid << ": " << kernel->name(); -// if(kernel->get_parent()) -// kernel_stat << ", parent " << kernel->get_parent()->get_uid() << -// ", launch " << kernel->launch_cycle; -// kernel_stat<< ", start " << kernel->start_cycle << -// ", end " << kernel->end_cycle << ", retire " << gpu_sim_cycle + gpu_tot_sim_cycle << "\n"; -// printf("kernel %d finishes, retires from stream %d\n", grid_uid, stream->get_uid()); -// kernel_stat.flush(); -// kernel_stat.close(); - stream->record_next_done(); - m_grid_id_to_stream.erase(grid_uid); - kernel->notify_parent_finished(); - delete kernel; - return true; - } + // Jin: should check children kernels for CDP + if (kernel->is_finished()) { + // std::ofstream kernel_stat("kernel_stat.txt", + // std::ofstream::out | std::ofstream::app); + // kernel_stat<< " kernel " << grid_uid << ": " << + // kernel->name(); + // if(kernel->get_parent()) + // kernel_stat << ", parent " << + // kernel->get_parent()->get_uid() << + // ", launch " << kernel->launch_cycle; + // kernel_stat<< ", start " << kernel->start_cycle << + // ", end " << kernel->end_cycle << ", retire " << + // gpu_sim_cycle + gpu_tot_sim_cycle << "\n"; + // printf("kernel %d finishes, retires from stream %d\n", + // grid_uid, stream->get_uid()); + // kernel_stat.flush(); + // kernel_stat.close(); + stream->record_next_done(); + m_grid_id_to_stream.erase(grid_uid); + kernel->notify_parent_finished(); + delete kernel; + return true; } + } - return false; + return false; } -void stream_manager::stop_all_running_kernels(){ - pthread_mutex_lock(&m_lock); +void stream_manager::stop_all_running_kernels() { + pthread_mutex_lock(&m_lock); - // Signal m_gpu to stop all running kernels - m_gpu->stop_all_running_kernels(); + // Signal m_gpu to stop all running kernels + m_gpu->stop_all_running_kernels(); - // Clean up all streams waiting on running kernels - int count=0; - while(check_finished_kernel()){ - count++; - } + // Clean up all streams waiting on running kernels + int count = 0; + while (check_finished_kernel()) { + count++; + } - // If any kernels completed, print out the current stats - if(count > 0) - m_gpu->print_stats(); + // If any kernels completed, print out the current stats + if (count > 0) m_gpu->print_stats(); - pthread_mutex_unlock(&m_lock); + pthread_mutex_unlock(&m_lock); } -stream_operation stream_manager::front() -{ - // called by gpu simulation thread - stream_operation result; -// if( concurrent_streams_empty() ) - m_service_stream_zero = true; - if( m_service_stream_zero ) { - if( !m_stream_zero.empty() && !m_stream_zero.busy() ) { - result = m_stream_zero.next(); - if( result.is_kernel() ) { - unsigned grid_id = result.get_kernel()->get_uid(); - m_grid_id_to_stream[grid_id] = &m_stream_zero; - } - } else { - m_service_stream_zero = false; - } +stream_operation stream_manager::front() { + // called by gpu simulation thread + stream_operation result; + // if( concurrent_streams_empty() ) + m_service_stream_zero = true; + if (m_service_stream_zero) { + if (!m_stream_zero.empty() && !m_stream_zero.busy()) { + result = m_stream_zero.next(); + if (result.is_kernel()) { + unsigned grid_id = result.get_kernel()->get_uid(); + m_grid_id_to_stream[grid_id] = &m_stream_zero; + } + } else { + m_service_stream_zero = false; } - - if(!m_service_stream_zero) - { - std::list<struct CUstream_st*>::iterator s; - for( s=m_streams.begin(); s != m_streams.end(); s++) { - CUstream_st *stream = *s; - if( !stream->busy() && !stream->empty() ) { - result = stream->next(); - if( result.is_kernel() ) { - unsigned grid_id = result.get_kernel()->get_uid(); - m_grid_id_to_stream[grid_id] = stream; - } - break; - } + } + + if (!m_service_stream_zero) { + std::list<struct CUstream_st *>::iterator s; + for (s = m_streams.begin(); s != m_streams.end(); s++) { + CUstream_st *stream = *s; + if (!stream->busy() && !stream->empty()) { + result = stream->next(); + if (result.is_kernel()) { + unsigned grid_id = result.get_kernel()->get_uid(); + m_grid_id_to_stream[grid_id] = stream; } + break; + } } - return result; + } + return result; } -void stream_manager::add_stream( struct CUstream_st *stream ) -{ - // called by host thread - pthread_mutex_lock(&m_lock); - m_streams.push_back(stream); - pthread_mutex_unlock(&m_lock); +void stream_manager::add_stream(struct CUstream_st *stream) { + // called by host thread + pthread_mutex_lock(&m_lock); + m_streams.push_back(stream); + pthread_mutex_unlock(&m_lock); } -void stream_manager::destroy_stream( CUstream_st *stream ) -{ - // called by host thread - pthread_mutex_lock(&m_lock); - while( !stream->empty() ) - ; - std::list<CUstream_st *>::iterator s; - for( s=m_streams.begin(); s != m_streams.end(); s++ ) { - if( *s == stream ) { - m_streams.erase(s); - break; - } +void stream_manager::destroy_stream(CUstream_st *stream) { + // called by host thread + pthread_mutex_lock(&m_lock); + while (!stream->empty()) + ; + std::list<CUstream_st *>::iterator s; + for (s = m_streams.begin(); s != m_streams.end(); s++) { + if (*s == stream) { + m_streams.erase(s); + break; } - delete stream; - pthread_mutex_unlock(&m_lock); + } + delete stream; + pthread_mutex_unlock(&m_lock); } -bool stream_manager::concurrent_streams_empty() -{ - bool result = true; - if (m_streams.empty()) - return true; - // called by gpu simulation thread - std::list<struct CUstream_st *>::iterator s; - for( s=m_streams.begin(); s!=m_streams.end();++s ) { - struct CUstream_st *stream = *s; - if( !stream->empty() ) { - //stream->print(stdout); - result = false; - break; - } +bool stream_manager::concurrent_streams_empty() { + bool result = true; + if (m_streams.empty()) return true; + // called by gpu simulation thread + std::list<struct CUstream_st *>::iterator s; + for (s = m_streams.begin(); s != m_streams.end(); ++s) { + struct CUstream_st *stream = *s; + if (!stream->empty()) { + // stream->print(stdout); + result = false; + break; } - return result; + } + return result; } -bool stream_manager::empty_protected() -{ - bool result = true; - pthread_mutex_lock(&m_lock); - if( !concurrent_streams_empty() ) - result = false; - if( !m_stream_zero.empty() ) - result = false; - pthread_mutex_unlock(&m_lock); - return result; +bool stream_manager::empty_protected() { + bool result = true; + pthread_mutex_lock(&m_lock); + if (!concurrent_streams_empty()) result = false; + if (!m_stream_zero.empty()) result = false; + pthread_mutex_unlock(&m_lock); + return result; } -bool stream_manager::empty() -{ - bool result = true; - if( !concurrent_streams_empty() ) - result = false; - if( !m_stream_zero.empty() ) - result = false; - return result; +bool stream_manager::empty() { + bool result = true; + if (!concurrent_streams_empty()) result = false; + if (!m_stream_zero.empty()) result = false; + return result; } - -void stream_manager::print( FILE *fp) -{ - pthread_mutex_lock(&m_lock); - print_impl(fp); - pthread_mutex_unlock(&m_lock); +void stream_manager::print(FILE *fp) { + pthread_mutex_lock(&m_lock); + print_impl(fp); + pthread_mutex_unlock(&m_lock); } -void stream_manager::print_impl( FILE *fp) -{ - fprintf(fp,"GPGPU-Sim API: Stream Manager State\n"); - std::list<struct CUstream_st *>::iterator s; - for( s=m_streams.begin(); s!=m_streams.end();++s ) { - struct CUstream_st *stream = *s; - if( !stream->empty() ) - stream->print(fp); - } - if( !m_stream_zero.empty() ) - m_stream_zero.print(fp); +void stream_manager::print_impl(FILE *fp) { + fprintf(fp, "GPGPU-Sim API: Stream Manager State\n"); + std::list<struct CUstream_st *>::iterator s; + for (s = m_streams.begin(); s != m_streams.end(); ++s) { + struct CUstream_st *stream = *s; + if (!stream->empty()) stream->print(fp); + } + if (!m_stream_zero.empty()) m_stream_zero.print(fp); } -void stream_manager::push( stream_operation op ) -{ - struct CUstream_st *stream = op.get_stream(); - - // block if stream 0 (or concurrency disabled) and pending concurrent operations exist - bool block= !stream || m_cuda_launch_blocking; - while(block) { - pthread_mutex_lock(&m_lock); - block = !concurrent_streams_empty(); - pthread_mutex_unlock(&m_lock); - }; +void stream_manager::push(stream_operation op) { + struct CUstream_st *stream = op.get_stream(); + // block if stream 0 (or concurrency disabled) and pending concurrent + // operations exist + bool block = !stream || m_cuda_launch_blocking; + while (block) { pthread_mutex_lock(&m_lock); - if(!m_gpu->cycle_insn_cta_max_hit()) { - // Accept the stream operation if the maximum cycle/instruction/cta counts are not triggered - if( stream && !m_cuda_launch_blocking ) { - stream->push(op); - } else { - op.set_stream(&m_stream_zero); - m_stream_zero.push(op); - } - }else { - // Otherwise, ignore operation and continue - printf("GPGPU-Sim API: Maximum cycle, instruction, or CTA count hit. Skipping:"); - op.print(stdout); - printf("\n"); - } - if(g_debug_execution >= 3) - print_impl(stdout); + block = !concurrent_streams_empty(); pthread_mutex_unlock(&m_lock); - if( m_cuda_launch_blocking || stream == NULL ) { - unsigned int wait_amount = 100; - unsigned int wait_cap = 100000; // 100ms - while( !empty() ) { - // sleep to prevent CPU hog by empty spin - // sleep time increased exponentially ensure fast response when needed - usleep(wait_amount); - wait_amount *= 2; - if (wait_amount > wait_cap) - wait_amount = wait_cap; - } + }; + + pthread_mutex_lock(&m_lock); + if (!m_gpu->cycle_insn_cta_max_hit()) { + // Accept the stream operation if the maximum cycle/instruction/cta counts + // are not triggered + if (stream && !m_cuda_launch_blocking) { + stream->push(op); + } else { + op.set_stream(&m_stream_zero); + m_stream_zero.push(op); } + } else { + // Otherwise, ignore operation and continue + printf( + "GPGPU-Sim API: Maximum cycle, instruction, or CTA count hit. " + "Skipping:"); + op.print(stdout); + printf("\n"); + } + if (g_debug_execution >= 3) print_impl(stdout); + pthread_mutex_unlock(&m_lock); + if (m_cuda_launch_blocking || stream == NULL) { + unsigned int wait_amount = 100; + unsigned int wait_cap = 100000; // 100ms + while (!empty()) { + // sleep to prevent CPU hog by empty spin + // sleep time increased exponentially ensure fast response when needed + usleep(wait_amount); + wait_amount *= 2; + if (wait_amount > wait_cap) wait_amount = wait_cap; + } + } } -void stream_manager::pushCudaStreamWaitEventToAllStreams( CUevent_st *e, unsigned int flags ){ - std::list<CUstream_st *>::iterator s; - for( s=m_streams.begin(); s != m_streams.end(); s++ ) { - stream_operation op(*s,e,flags); - push(op); - } +void stream_manager::pushCudaStreamWaitEventToAllStreams(CUevent_st *e, + unsigned int flags) { + std::list<CUstream_st *>::iterator s; + for (s = m_streams.begin(); s != m_streams.end(); s++) { + stream_operation op(*s, e, flags); + push(op); + } } diff --git a/src/stream_manager.h b/src/stream_manager.h index 3fbdbaf..88e28c8 100644 --- a/src/stream_manager.h +++ b/src/stream_manager.h @@ -7,14 +7,16 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this +// Redistributions in binary form must reproduce the above copyright notice, +// this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -28,248 +30,249 @@ #ifndef STREAM_MANAGER_H_INCLUDED #define STREAM_MANAGER_H_INCLUDED -#include "abstract_hardware_model.h" -#include <list> #include <pthread.h> #include <time.h> +#include <list> +#include "abstract_hardware_model.h" -//class stream_barrier { -//public: +// class stream_barrier { +// public: // stream_barrier() { m_pending_streams=0; } // void inc() { m_pending_streams++; } // void dec() { assert(m_pending_streams); m_pending_streams--; } // unsigned value() const { return m_pending_streams; } -//private: +// private: // unsigned m_pending_streams; //}; enum stream_operation_type { - stream_no_op, - stream_memcpy_host_to_device, - stream_memcpy_device_to_host, - stream_memcpy_device_to_device, - stream_memcpy_to_symbol, - stream_memcpy_from_symbol, - stream_kernel_launch, - stream_event, - stream_wait_event + stream_no_op, + stream_memcpy_host_to_device, + stream_memcpy_device_to_host, + stream_memcpy_device_to_device, + stream_memcpy_to_symbol, + stream_memcpy_from_symbol, + stream_kernel_launch, + stream_event, + stream_wait_event }; class stream_operation { -public: - stream_operation() - { - m_kernel=NULL; - m_type = stream_no_op; - m_stream = NULL; - m_done=true; - } - stream_operation( const void *src, const char *symbol, size_t count, size_t offset, struct CUstream_st *stream ) - { - m_kernel=NULL; - m_stream = stream; - m_type=stream_memcpy_to_symbol; - m_host_address_src=src; - m_symbol=symbol; - m_cnt=count; - m_offset=offset; - m_done=false; - } - stream_operation( const char *symbol, void *dst, size_t count, size_t offset, struct CUstream_st *stream ) - { - m_kernel=NULL; - m_stream = stream; - m_type=stream_memcpy_from_symbol; - m_host_address_dst=dst; - m_symbol=symbol; - m_cnt=count; - m_offset=offset; - m_done=false; - } - stream_operation( kernel_info_t *kernel, bool sim_mode, struct CUstream_st *stream ) - { - m_type=stream_kernel_launch; - m_kernel=kernel; - m_sim_mode=sim_mode; - m_stream=stream; - m_done=false; - } - stream_operation( struct CUevent_st *e, struct CUstream_st *stream ) - { - m_kernel=NULL; - m_type=stream_event; - m_event=e; - m_stream=stream; - m_done=false; - } - stream_operation( struct CUstream_st *stream, class CUevent_st *e, unsigned int flags ) - { - m_kernel=NULL; - m_type=stream_wait_event; - m_event=e; - m_stream=stream; - m_done=false; - } - stream_operation( const void *host_address_src, size_t device_address_dst, size_t cnt, struct CUstream_st *stream ) - { - m_kernel=NULL; - m_type=stream_memcpy_host_to_device; - m_host_address_src =host_address_src; - m_device_address_dst=device_address_dst; - m_host_address_dst=NULL; - m_device_address_src=0; - m_cnt=cnt; - m_stream=stream; - m_sim_mode=false; - m_done=false; - } - stream_operation( size_t device_address_src, void *host_address_dst, size_t cnt, struct CUstream_st *stream ) - { - m_kernel=NULL; - m_type=stream_memcpy_device_to_host; - m_device_address_src=device_address_src; - m_host_address_dst=host_address_dst; - m_device_address_dst=0; - m_host_address_src=NULL; - m_cnt=cnt; - m_stream=stream; - m_sim_mode=false; - m_done=false; - } - stream_operation( size_t device_address_src, size_t device_address_dst, size_t cnt, struct CUstream_st *stream ) - { - m_kernel=NULL; - m_type=stream_memcpy_device_to_device; - m_device_address_src=device_address_src; - m_device_address_dst=device_address_dst; - m_host_address_src=NULL; - m_host_address_dst=NULL; - m_cnt=cnt; - m_stream=stream; - m_sim_mode=false; - m_done=false; - } + public: + stream_operation() { + m_kernel = NULL; + m_type = stream_no_op; + m_stream = NULL; + m_done = true; + } + stream_operation(const void *src, const char *symbol, size_t count, + size_t offset, struct CUstream_st *stream) { + m_kernel = NULL; + m_stream = stream; + m_type = stream_memcpy_to_symbol; + m_host_address_src = src; + m_symbol = symbol; + m_cnt = count; + m_offset = offset; + m_done = false; + } + stream_operation(const char *symbol, void *dst, size_t count, size_t offset, + struct CUstream_st *stream) { + m_kernel = NULL; + m_stream = stream; + m_type = stream_memcpy_from_symbol; + m_host_address_dst = dst; + m_symbol = symbol; + m_cnt = count; + m_offset = offset; + m_done = false; + } + stream_operation(kernel_info_t *kernel, bool sim_mode, + struct CUstream_st *stream) { + m_type = stream_kernel_launch; + m_kernel = kernel; + m_sim_mode = sim_mode; + m_stream = stream; + m_done = false; + } + stream_operation(struct CUevent_st *e, struct CUstream_st *stream) { + m_kernel = NULL; + m_type = stream_event; + m_event = e; + m_stream = stream; + m_done = false; + } + stream_operation(struct CUstream_st *stream, class CUevent_st *e, + unsigned int flags) { + m_kernel = NULL; + m_type = stream_wait_event; + m_event = e; + m_stream = stream; + m_done = false; + } + stream_operation(const void *host_address_src, size_t device_address_dst, + size_t cnt, struct CUstream_st *stream) { + m_kernel = NULL; + m_type = stream_memcpy_host_to_device; + m_host_address_src = host_address_src; + m_device_address_dst = device_address_dst; + m_host_address_dst = NULL; + m_device_address_src = 0; + m_cnt = cnt; + m_stream = stream; + m_sim_mode = false; + m_done = false; + } + stream_operation(size_t device_address_src, void *host_address_dst, + size_t cnt, struct CUstream_st *stream) { + m_kernel = NULL; + m_type = stream_memcpy_device_to_host; + m_device_address_src = device_address_src; + m_host_address_dst = host_address_dst; + m_device_address_dst = 0; + m_host_address_src = NULL; + m_cnt = cnt; + m_stream = stream; + m_sim_mode = false; + m_done = false; + } + stream_operation(size_t device_address_src, size_t device_address_dst, + size_t cnt, struct CUstream_st *stream) { + m_kernel = NULL; + m_type = stream_memcpy_device_to_device; + m_device_address_src = device_address_src; + m_device_address_dst = device_address_dst; + m_host_address_src = NULL; + m_host_address_dst = NULL; + m_cnt = cnt; + m_stream = stream; + m_sim_mode = false; + m_done = false; + } - bool is_kernel() const { return m_type == stream_kernel_launch; } - bool is_mem() const { - return m_type == stream_memcpy_host_to_device || - m_type == stream_memcpy_device_to_host || - m_type == stream_memcpy_host_to_device; - } - bool is_noop() const { return m_type == stream_no_op; } - bool is_done() const { return m_done; } - kernel_info_t *get_kernel() { return m_kernel; } - bool do_operation( gpgpu_sim *gpu ); - void print( FILE *fp ) const; - struct CUstream_st *get_stream() { return m_stream; } - void set_stream( CUstream_st *stream ) { m_stream = stream; } + bool is_kernel() const { return m_type == stream_kernel_launch; } + bool is_mem() const { + return m_type == stream_memcpy_host_to_device || + m_type == stream_memcpy_device_to_host || + m_type == stream_memcpy_host_to_device; + } + bool is_noop() const { return m_type == stream_no_op; } + bool is_done() const { return m_done; } + kernel_info_t *get_kernel() { return m_kernel; } + bool do_operation(gpgpu_sim *gpu); + void print(FILE *fp) const; + struct CUstream_st *get_stream() { + return m_stream; + } + void set_stream(CUstream_st *stream) { m_stream = stream; } -private: - struct CUstream_st *m_stream; + private: + struct CUstream_st *m_stream; - bool m_done; + bool m_done; - stream_operation_type m_type; - size_t m_device_address_dst; - size_t m_device_address_src; - void *m_host_address_dst; - const void *m_host_address_src; - size_t m_cnt; + stream_operation_type m_type; + size_t m_device_address_dst; + size_t m_device_address_src; + void *m_host_address_dst; + const void *m_host_address_src; + size_t m_cnt; - const char *m_symbol; - size_t m_offset; + const char *m_symbol; + size_t m_offset; - bool m_sim_mode; - kernel_info_t *m_kernel; - struct CUevent_st *m_event; + bool m_sim_mode; + kernel_info_t *m_kernel; + struct CUevent_st *m_event; }; struct CUevent_st { -public: - CUevent_st( bool blocking ) - { - m_uid = ++m_next_event_uid; - m_blocking = blocking; - m_updates = 0; - m_wallclock = 0; - m_gpu_tot_sim_cycle = 0; - m_done = false; - } - void update( double cycle, time_t clk ) - { - m_updates++; - m_wallclock=clk; - m_gpu_tot_sim_cycle=cycle; - m_done = true; - } - //void set_done() { assert(!m_done); m_done=true; } - int get_uid() const { return m_uid; } - unsigned num_updates() const { return m_updates; } - bool done() const { return m_done; } - time_t clock() const { return m_wallclock; } -private: - int m_uid; - bool m_blocking; - bool m_done; - int m_updates; - time_t m_wallclock; - double m_gpu_tot_sim_cycle; + public: + CUevent_st(bool blocking) { + m_uid = ++m_next_event_uid; + m_blocking = blocking; + m_updates = 0; + m_wallclock = 0; + m_gpu_tot_sim_cycle = 0; + m_done = false; + } + void update(double cycle, time_t clk) { + m_updates++; + m_wallclock = clk; + m_gpu_tot_sim_cycle = cycle; + m_done = true; + } + // void set_done() { assert(!m_done); m_done=true; } + int get_uid() const { return m_uid; } + unsigned num_updates() const { return m_updates; } + bool done() const { return m_done; } + time_t clock() const { return m_wallclock; } + + private: + int m_uid; + bool m_blocking; + bool m_done; + int m_updates; + time_t m_wallclock; + double m_gpu_tot_sim_cycle; - static int m_next_event_uid; + static int m_next_event_uid; }; struct CUstream_st { -public: - CUstream_st(); - bool empty(); - bool busy(); - void synchronize(); - void push( const stream_operation &op ); - void record_next_done(); - stream_operation next(); - void cancel_front(); //front operation fails, cancle the pending status - stream_operation &front() { return m_operations.front(); } - void print( FILE *fp ); - unsigned get_uid() const { return m_uid; } + public: + CUstream_st(); + bool empty(); + bool busy(); + void synchronize(); + void push(const stream_operation &op); + void record_next_done(); + stream_operation next(); + void cancel_front(); // front operation fails, cancle the pending status + stream_operation &front() { return m_operations.front(); } + void print(FILE *fp); + unsigned get_uid() const { return m_uid; } -private: - unsigned m_uid; - static unsigned sm_next_stream_uid; + private: + unsigned m_uid; + static unsigned sm_next_stream_uid; - std::list<stream_operation> m_operations; - bool m_pending; // front operation has started but not yet completed + std::list<stream_operation> m_operations; + bool m_pending; // front operation has started but not yet completed - pthread_mutex_t m_lock; // ensure only one host or gpu manipulates stream operation at one time + pthread_mutex_t m_lock; // ensure only one host or gpu manipulates stream + // operation at one time }; class stream_manager { -public: - stream_manager( gpgpu_sim *gpu, bool cuda_launch_blocking ); - bool register_finished_kernel(unsigned grid_uid ); - bool check_finished_kernel( ); - stream_operation front(); - void add_stream( CUstream_st *stream ); - void destroy_stream( CUstream_st *stream ); - bool concurrent_streams_empty(); - bool empty_protected(); - bool empty(); - void print( FILE *fp); - void push( stream_operation op ); - void pushCudaStreamWaitEventToAllStreams( CUevent_st *e, unsigned int flags ); - bool operation(bool * sim); - void stop_all_running_kernels(); - unsigned size() {return m_streams.size(); }; - bool is_blocking() {return m_cuda_launch_blocking; }; -private: - void print_impl( FILE *fp); + public: + stream_manager(gpgpu_sim *gpu, bool cuda_launch_blocking); + bool register_finished_kernel(unsigned grid_uid); + bool check_finished_kernel(); + stream_operation front(); + void add_stream(CUstream_st *stream); + void destroy_stream(CUstream_st *stream); + bool concurrent_streams_empty(); + bool empty_protected(); + bool empty(); + void print(FILE *fp); + void push(stream_operation op); + void pushCudaStreamWaitEventToAllStreams(CUevent_st *e, unsigned int flags); + bool operation(bool *sim); + void stop_all_running_kernels(); + unsigned size() { return m_streams.size(); }; + bool is_blocking() { return m_cuda_launch_blocking; }; + + private: + void print_impl(FILE *fp); - bool m_cuda_launch_blocking; - gpgpu_sim *m_gpu; - std::list<CUstream_st *> m_streams; - std::map<unsigned,CUstream_st *> m_grid_id_to_stream; - CUstream_st m_stream_zero; - bool m_service_stream_zero; - pthread_mutex_t m_lock; + bool m_cuda_launch_blocking; + gpgpu_sim *m_gpu; + std::list<CUstream_st *> m_streams; + std::map<unsigned, CUstream_st *> m_grid_id_to_stream; + CUstream_st m_stream_zero; + bool m_service_stream_zero; + pthread_mutex_t m_lock; }; #endif diff --git a/src/tr1_hash_map.h b/src/tr1_hash_map.h index 8c7513e..0672ef8 100644 --- a/src/tr1_hash_map.h +++ b/src/tr1_hash_map.h @@ -7,14 +7,16 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this +// Redistributions in binary form must reproduce the above copyright notice, +// this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -25,26 +27,27 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#pragma once +#pragma once // detection and fallback for unordered_map in C++0x #ifdef __cplusplus - // detect GCC 4.3 or later and use unordered map (part of C++0x) - // unordered map doesn't play nice with _GLIBCXX_DEBUG, just use a map if its enabled. - #if defined( __GNUC__ ) and not defined( _GLIBCXX_DEBUG ) - #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 - #include <unordered_map> - #define tr1_hash_map std::unordered_map - #define tr1_hash_map_ismap 0 - #else - #include <map> - #define tr1_hash_map std::map - #define tr1_hash_map_ismap 1 - #endif - #else - #include <map> - #define tr1_hash_map std::map - #define tr1_hash_map_ismap 1 - #endif +// detect GCC 4.3 or later and use unordered map (part of C++0x) +// unordered map doesn't play nice with _GLIBCXX_DEBUG, just use a map if its +// enabled. +#if defined(__GNUC__) and not defined(_GLIBCXX_DEBUG) +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 +#include <unordered_map> +#define tr1_hash_map std::unordered_map +#define tr1_hash_map_ismap 0 +#else +#include <map> +#define tr1_hash_map std::map +#define tr1_hash_map_ismap 1 +#endif +#else +#include <map> +#define tr1_hash_map std::map +#define tr1_hash_map_ismap 1 +#endif #endif diff --git a/src/trace.cc b/src/trace.cc index 5171e46..b5c2524 100644 --- a/src/trace.cc +++ b/src/trace.cc @@ -7,14 +7,16 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this +// Redistributions in binary form must reproduce the above copyright notice, +// this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -30,27 +32,27 @@ namespace Trace { - #define TS_TUP_BEGIN(X) const char* trace_streams_str[] = { #define TS_TUP(X) #X -#define TS_TUP_END(X) }; +#define TS_TUP_END(X) \ + } \ + ; #include "trace_streams.tup" #undef TS_TUP_BEGIN #undef TS_TUP #undef TS_TUP_END - bool enabled = false; - int sampling_core = 0; - int sampling_memory_partition = -1; - bool trace_streams_enabled[NUM_TRACE_STREAMS] = {false}; - const char* config_str; +bool enabled = false; +int sampling_core = 0; +int sampling_memory_partition = -1; +bool trace_streams_enabled[NUM_TRACE_STREAMS] = {false}; +const char* config_str; - void init() - { - for ( unsigned i = 0; i < NUM_TRACE_STREAMS; ++i ) { - if ( strstr( config_str, trace_streams_str[i] ) != NULL ) { - trace_streams_enabled[ i ] = true; - } - } +void init() { + for (unsigned i = 0; i < NUM_TRACE_STREAMS; ++i) { + if (strstr(config_str, trace_streams_str[i]) != NULL) { + trace_streams_enabled[i] = true; } -} + } +} +} diff --git a/src/trace.h b/src/trace.h index 0b96dcf..c4e0001 100644 --- a/src/trace.h +++ b/src/trace.h @@ -7,14 +7,16 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this +// Redistributions in binary form must reproduce the above copyright notice, +// this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -35,52 +37,57 @@ namespace Trace { #define TS_TUP_BEGIN(X) enum X { #define TS_TUP(X) X -#define TS_TUP_END(X) }; +#define TS_TUP_END(X) \ + } \ + ; #include "trace_streams.tup" #undef TS_TUP_BEGIN #undef TS_TUP #undef TS_TUP_END - extern bool enabled; - extern int sampling_core; - extern int sampling_memory_partition; - extern const char* trace_streams_str[]; - extern bool trace_streams_enabled[NUM_TRACE_STREAMS]; - extern const char* config_str; +extern bool enabled; +extern int sampling_core; +extern int sampling_memory_partition; +extern const char* trace_streams_str[]; +extern bool trace_streams_enabled[NUM_TRACE_STREAMS]; +extern const char* config_str; - void init(); - -} // namespace Trace +void init(); +} // namespace Trace #if TRACING_ON #define SIM_PRINT_STR "GPGPU-Sim Cycle %llu: %s - " #define DTRACE(x) ((Trace::trace_streams_enabled[Trace::x]) && Trace::enabled) -#define DPRINTF(x, ...) do {\ - if (DTRACE(x)) {\ - printf( SIM_PRINT_STR,\ - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle,\ - Trace::trace_streams_str[Trace::x] );\ - printf(__VA_ARGS__);\ - }\ -} while (0) +#define DPRINTF(x, ...) \ + do { \ + if (DTRACE(x)) { \ + printf(SIM_PRINT_STR, m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle, \ + Trace::trace_streams_str[Trace::x]); \ + printf(__VA_ARGS__); \ + } \ + } while (0) -#define DPRINTFG(x, ...) do {\ - if (DTRACE(x)) {\ - printf( SIM_PRINT_STR,\ - gpu_sim_cycle + gpu_tot_sim_cycle,\ - Trace::trace_streams_str[Trace::x] );\ - printf(__VA_ARGS__);\ - }\ -} while (0) +#define DPRINTFG(x, ...) \ + do { \ + if (DTRACE(x)) { \ + printf(SIM_PRINT_STR, gpu_sim_cycle + gpu_tot_sim_cycle, \ + Trace::trace_streams_str[Trace::x]); \ + printf(__VA_ARGS__); \ + } \ + } while (0) -#else +#else #define DTRACE(x) (false) -#define DPRINTF(x, ...) do {} while (0) -#define DPRINTFG(x, ...) do {} while (0) +#define DPRINTF(x, ...) \ + do { \ + } while (0) +#define DPRINTFG(x, ...) \ + do { \ + } while (0) -#endif +#endif -#endif +#endif |
