diff options
| author | Tor Aamodt <[email protected]> | 2010-08-08 12:17:43 -0800 |
|---|---|---|
| committer | Tor Aamodt <[email protected]> | 2010-08-08 12:17:43 -0800 |
| commit | ef53bd94e416c74a3ea3b4d6240eb8f043e86e60 (patch) | |
| tree | 5b0a8bb30f9472188390360f123d5d91a606027f /src/cuda-sim | |
| parent | 43eb0e822424b39b52091f45725376cc903b08ee (diff) | |
refactoring: moving 'loading' operations into ptx_loader.*
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7166]
Diffstat (limited to 'src/cuda-sim')
| -rw-r--r-- | src/cuda-sim/Makefile | 3 | ||||
| -rw-r--r-- | src/cuda-sim/cuda-sim.cc | 378 | ||||
| -rw-r--r-- | src/cuda-sim/cuda-sim.h | 12 | ||||
| -rw-r--r-- | src/cuda-sim/instructions.cc | 7 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_ir.cc | 172 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_ir.h | 23 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_loader.cc | 303 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_loader.h | 80 |
8 files changed, 579 insertions, 399 deletions
diff --git a/src/cuda-sim/Makefile b/src/cuda-sim/Makefile index 9d43f58..6140048 100644 --- a/src/cuda-sim/Makefile +++ b/src/cuda-sim/Makefile @@ -91,7 +91,7 @@ ifeq ($(GNUC_CPP0X),1) endif endif -OBJS := cuda_device_printf.o instructions.o cuda-sim.o ptx_ir.o ptx_sim.o memory.o ptx-stats.o ptx.tab.o lex.ptx_.o ptxinfo.tab.o lex.ptxinfo_.o +OBJS := ptx_loader.o cuda_device_printf.o instructions.o cuda-sim.o ptx_ir.o ptx_sim.o memory.o ptx-stats.o ptx.tab.o lex.ptx_.o ptxinfo.tab.o lex.ptxinfo_.o CUDART_VERSION:=$(shell nvcc --version | awk '/release/ {print $$5;}' | sed 's/,//' | sed 's/\./ /' | awk '{printf("%02u%02u", 10*int($$1), 10*$$2);}') @@ -166,6 +166,7 @@ depend: instructions.o: instructions.h ptx.tab.c cuda_device_printf.o: ptx.tab.c ptx_ir.o: ptx.tab.c ptx_parser_decode.def +ptx_loader.o: ptx.tab.c # DO NOT DELETE diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 74b18bc..f5c283e 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -68,7 +68,6 @@ #include "ptx_ir.h" #include "ptx_sim.h" #include <stdio.h> -#include <dirent.h> #include "opcodes.h" #include "../intersim/statwraper.h" @@ -78,6 +77,7 @@ #include "../abstract_hardware_model.h" #include "memory.h" #include "ptx-stats.h" +#include "ptx_loader.h" extern bool g_interactive_debugger_enabled; @@ -85,30 +85,15 @@ int gpgpu_ptx_instruction_classification=0; void ** g_inst_classification_stat = NULL; void ** g_inst_op_classification_stat= NULL; int g_ptx_kernel_count = -1; // used for classification stat collection purposes -extern "C" int ptx_parse(); -extern "C" int ptx__scan_string(const char*); -extern "C" int ptx_debug; -extern "C" FILE *ptx_in; - -extern "C" const char *g_ptxinfo_filename = NULL; -extern "C" int ptxinfo_parse(); -extern "C" int ptxinfo_debug; -extern "C" FILE *ptxinfo_in; int g_debug_execution = 0; int g_debug_thread_uid = 0; addr_t g_debug_pc = 0xBEEF1518; -int g_override_embedded_ptx = false; const char *g_filename; bool g_debug_ir_generation = false; unsigned g_ptx_sim_num_insn = 0; -extern memory_space *g_global_mem; -extern memory_space *g_param_mem; -extern memory_space *g_tex_mem; -extern memory_space *g_surf_mem; - std::map<const struct textureReference*,const struct cudaArray*> TextureToArrayMap; // texture bindings std::map<const struct textureReference*, const struct textureInfo*> TextureToInfoMap; std::map<std::string, const struct textureReference*> NameToTextureMap; @@ -309,100 +294,6 @@ void gpgpu_ptx_sim_init_memory() } } -int load_static_globals( symbol_table *symtab, unsigned min_gaddr, unsigned max_gaddr) -{ - printf( "GPGPU-Sim PTX: loading globals with explicit initializers... \n" ); - fflush(stdout); - int ng_bytes=0; - symbol_table::iterator g=symtab->global_iterator_begin(); - - for ( ; g!=symtab->global_iterator_end(); g++) { - symbol *global = *g; - if ( global->has_initializer() ) { - printf( "GPGPU-Sim PTX: initializing '%s' ... ", global->name().c_str() ); - unsigned addr=global->get_address(); - const type_info *type = global->type(); - type_info_key ti=type->get_key(); - size_t size; - int t; - ti.type_decode(size,t); - int nbytes = size/8; - int offset=0; - std::list<operand_info> init_list = global->get_initializer(); - for ( std::list<operand_info>::iterator i=init_list.begin(); i!=init_list.end(); i++ ) { - operand_info op = *i; - ptx_reg_t value = op.get_literal_value(); - assert( (addr+offset+nbytes) < min_gaddr ); // min_gaddr is start of "heap" for cudaMalloc - g_global_mem->write(addr+offset,nbytes,&value,NULL,NULL); // assuming little endian here - offset+=nbytes; - ng_bytes+=nbytes; - } - printf(" wrote %u bytes\n", offset ); - } - } - printf( "GPGPU-Sim PTX: finished loading globals (%u bytes total).\n", ng_bytes ); - fflush(stdout); - return ng_bytes; -} - -int load_constants( symbol_table *symtab, addr_t min_gaddr ) -{ - printf( "GPGPU-Sim PTX: loading constants with explicit initializers... " ); - fflush(stdout); - int nc_bytes = 0; - symbol_table::iterator g=symtab->const_iterator_begin(); - - for ( ; g!=symtab->const_iterator_end(); g++) { - symbol *constant = *g; - if ( constant->is_const() && constant->has_initializer() ) { - - // get the constant element data size - int basic_type; - size_t num_bits; - constant->type()->get_key().type_decode(num_bits,basic_type); - - std::list<operand_info> init_list = constant->get_initializer(); - int nbytes_written = 0; - for ( std::list<operand_info>::iterator i=init_list.begin(); i!=init_list.end(); i++ ) { - operand_info op = *i; - ptx_reg_t value = op.get_literal_value(); - int nbytes = num_bits/8; - switch ( op.get_type() ) { - case int_t: assert(nbytes >= 1); break; - case float_op_t: assert(nbytes == 4); break; - case double_op_t: assert(nbytes >= 4); break; // account for double DEMOTING - default: - abort(); - } - unsigned addr=constant->get_address() + nbytes_written; - assert( addr+nbytes < min_gaddr ); - - g_global_mem->write(addr,nbytes,&value,NULL,NULL); // assume little endian (so u8 is the first byte in u32) - nc_bytes+=nbytes; - nbytes_written += nbytes; - } - } - } - printf( " done.\n"); - fflush(stdout); - return nc_bytes; -} - -#define GLOBAL_HEAP_START 0x10000000 - // start allocating from this address (lower values used for allocating globals in .ptx file) - -#define SHARED_MEM_SIZE_MAX (64*1024) -#define LOCAL_MEM_SIZE_MAX 1024 -#define MAX_STREAMING_MULTIPROCESSORS 64 -#define MAX_THREAD_PER_SM 1024 -#define TOTAL_LOCAL_MEM_PER_SM (MAX_THREAD_PER_SM*LOCAL_MEM_SIZE_MAX) -#define TOTAL_SHARED_MEM (MAX_STREAMING_MULTIPROCESSORS*SHARED_MEM_SIZE_MAX) -#define TOTAL_LOCAL_MEM (MAX_STREAMING_MULTIPROCESSORS*MAX_THREAD_PER_SM*LOCAL_MEM_SIZE_MAX) -#define SHARED_GENERIC_START (GLOBAL_HEAP_START-TOTAL_SHARED_MEM) -#define LOCAL_GENERIC_START (SHARED_GENERIC_START-TOTAL_LOCAL_MEM) - -#define STATIC_ALLOC_LIMIT (GLOBAL_HEAP_START - (TOTAL_LOCAL_MEM+TOTAL_SHARED_MEM)) - addr_t shared_to_generic( unsigned smid, addr_t addr ) { assert( addr < SHARED_MEM_SIZE_MAX ); @@ -1340,7 +1231,6 @@ std::map<const void*,std::string> g_const_name_lookup; // indexed by hostVar std::map<const void*,std::string> g_global_name_lookup; // indexed by hostVar std::set<std::string> g_globals; std::set<std::string> g_constants; -extern std::map<std::string,symbol_table*> g_sym_name_to_symbol_table; void gpgpu_ptx_sim_register_const_variable(void *hostVar, const char *deviceName, size_t size ) { @@ -1432,20 +1322,9 @@ int g_ptx_sim_mode=0; // used by libcuda.a if non-zer cudaLaunch() will call gpgpu_ptx_sim_main_func() // if zero it calls gpgpu_ptx_sim_main_perf() -#if defined(__APPLE__) -int ptx_file_filter(struct dirent *de ) -#else -int ptx_file_filter(const struct dirent *de ) -#endif -{ - const char *tmp = strstr(de->d_name,".ptx"); - if ( tmp != NULL && tmp[4] == 0 ) { - return 1; - } - return 0; -} +extern "C" int ptx_debug; -void read_environment_variables() +void read_sim_environment_variables() { ptx_debug = 0; g_debug_execution = 0; @@ -1503,261 +1382,10 @@ void read_environment_variables() } } -static FILE *open_ptxinfo (const char* ptx_filename) -{ - const int ptx_fnamelen = strlen(ptx_filename); - char *ptxi_fname = new char[ptx_fnamelen+5]; - strcpy (ptxi_fname, ptx_filename); - strcpy (ptxi_fname+ptx_fnamelen, "info"); - - //ptxinfo_debug=1; - g_ptxinfo_filename = ptxi_fname; - FILE *f = fopen (ptxi_fname, "rt"); - return f; -} -struct ptx_info_t { - char *str; - char *fname; - ptx_info_t *next; -}; -ptx_info_t *g_ptx_source_array = NULL; -unsigned g_used_embedded_ptx_files; -extern double g_ptx_version; -void gpgpu_ptx_sim_add_ptxstring( const char *ptx_string, const char *sourcefname ) -{ - ptx_info_t *t = new ptx_info_t; - t->next = NULL; - t->str = strdup(ptx_string); - t->fname = strdup(sourcefname); - - // put ptx source into a fifo - if (g_ptx_source_array == NULL) { - // first ptx source - g_ptx_source_array = t; - } else { - // insert subsequent ptx source at the end of queue - ptx_info_t *l_ptx_source = g_ptx_source_array; - while (l_ptx_source->next != NULL) { - l_ptx_source = l_ptx_source->next; - } - l_ptx_source->next = t; - } -} -const ptx_instruction *ptx_instruction_lookup( const char *filename, unsigned linenumber ); - -void print_ptx_file( const char *p, unsigned source_num, const char *filename ) -{ - printf("\nGPGPU-Sim PTX: file _%u.ptx contents:\n\n", source_num ); - char *s = strdup(p); - char *t = s; - unsigned n=1; - while ( *t != '\0' ) { - char *u = t; - while ( (*u != '\n') && (*u != '\0') ) u++; - unsigned last = (*u == '\0'); - *u = '\0'; - const ptx_instruction *pI = ptx_instruction_lookup(filename,n); - char pc[64]; - if( pI && pI->get_PC() ) - snprintf(pc,64,"%4u", pI->get_PC() ); - else - snprintf(pc,64," "); - printf(" _%u.ptx %4u (pc=%s): %s\n", source_num, n, pc, t ); - if ( last ) break; - t = u+1; - n++; - } - free(s); - fflush(stdout); -} - -extern int g_save_embedded_ptx; - -void gpgpu_ptx_sim_load_ptx_from_string( const char *p, unsigned source_num ) -{ - char buf[1024]; - snprintf(buf,1024,"_%u.ptx", source_num ); - if( g_save_embedded_ptx ) { - FILE *fp = fopen(buf,"w"); - fprintf(fp,"%s",p); - fclose(fp); - } - g_filename = strdup(buf); - init_parser(); - ptx__scan_string(p); - int errors = ptx_parse (); - if ( errors ) { - char fname[1024]; - snprintf(fname,1024,"_ptx_XXXXXX"); - int fd=mkstemp(fname); - close(fd); - printf("GPGPU-Sim PTX: parser error detected, exiting... but first extracting .ptx to \"%s\"\n", fname); - FILE *ptxfile = fopen(fname,"w"); - fprintf(ptxfile,"%s", p ); - fclose(ptxfile); - abort(); - exit(40); - } - - if ( g_debug_execution >= 100 ) - print_ptx_file(p,source_num,g_filename); - - printf("GPGPU-Sim PTX: finished parsing EMBEDDED .ptx file %s\n",g_filename); - - char fname[1024]; - snprintf(fname,1024,"_ptx_XXXXXX"); - int fd=mkstemp(fname); - close(fd); - - printf("GPGPU-Sim PTX: extracting embedded .ptx to temporary file \"%s\"\n", fname); - FILE *ptxfile = fopen(fname,"w"); - fprintf(ptxfile,"%s",p); - fclose(ptxfile); - - char fname2[1024]; - snprintf(fname2,1024,"_ptx2_XXXXXX"); - fd=mkstemp(fname2); - close(fd); - char commandline2[4096]; - snprintf(commandline2,4096,"cat %s | sed 's/.version 1.5/.version 1.4/' | sed 's/, texmode_independent//' | sed 's/\\(\\.extern \\.const\\[1\\] .b8 \\w\\+\\)\\[\\]/\\1\\[1\\]/' | sed 's/const\\[.\\]/const\\[0\\]/g' > %s", fname, fname2); - int result = system(commandline2); - if( result != 0 ) { - printf("GPGPU-Sim PTX: ERROR ** while loading PTX (a) %d\n", result); - printf(" Ensure you have write access to simulation directory\n"); - printf(" and have \'cat\' and \'sed\' in your path.\n"); - exit(1); - } - - char tempfile_ptxinfo[1024]; - snprintf(tempfile_ptxinfo,1024,"%sinfo",fname); - char commandline[1024]; - char extra_flags[1024]; - extra_flags[0]=0; -#if CUDART_VERSION >= 3000 - snprintf(extra_flags,1024,"--gpu-name=sm_20"); -#endif - snprintf(commandline,1024,"ptxas %s -v %s --output-file /dev/null 2> %s", - extra_flags, fname2, tempfile_ptxinfo); - printf("GPGPU-Sim PTX: generating ptxinfo using \"%s\"\n", commandline); - result = system(commandline); - if( result != 0 ) { - printf("GPGPU-Sim PTX: ERROR ** while loading PTX (b) %d\n", result); - printf(" Ensure ptxas is in your path.\n"); - exit(1); - } - - ptxinfo_in = fopen(tempfile_ptxinfo,"r"); - g_ptxinfo_filename = tempfile_ptxinfo; - ptxinfo_parse(); - snprintf(commandline,1024,"rm -f %s %s %s", fname, fname2, tempfile_ptxinfo); - printf("GPGPU-Sim PTX: removing ptxinfo using \"%s\"\n", commandline); - result = system(commandline); - if( result != 0 ) { - printf("GPGPU-Sim PTX: ERROR ** while loading PTX (c) %d\n", result); - exit(1); - } - g_filename = NULL; -} - -void gpgpu_ptx_assemble( std::string kname, void *kinfo ) -{ - function_info *func_info = (function_info *)kinfo; - if( func_info->is_extern() ) { - printf("GPGPU-Sim PTX: skipping assembly for extern declared function \'%s\'\n", func_info->get_name().c_str() ); - return; - } - if( g_kernel_name_to_symtab_lookup[ kname ] == NULL ) { - printf("\nGPGPU-Sim PTX: ERROR no information for kernel \'%s\'\n" - " this can happen for kernels contained in CUDA\n" - " libraries (such as CUBLAS, CUFFT, or CUDPP)\n", kname.c_str() ); - exit(1); - } - g_func_info = func_info; - func_info->ptx_assemble(); -} - -void gpgpu_ptx_sim_load_gpu_kernels() -{ - ptx_in = NULL; - if ( g_filename ) - ptx_in = fopen( g_filename, "r" ); - static unsigned source_num = 0; - gpgpu_ptx_sim_init_memory(); - if (ptx_in) { - init_parser(); - ptx_parse(); - ptxinfo_in = open_ptxinfo(g_filename); - ptxinfo_parse(); - load_static_globals(g_global_symbol_table,STATIC_ALLOC_LIMIT,0xFFFFFFFF); - load_constants(g_global_symbol_table,STATIC_ALLOC_LIMIT); - } else { - if (!g_override_embedded_ptx) { - g_used_embedded_ptx_files=1; - printf("GPGPU-Sim PTX: USING EMBEDDED .ptx files...\n"); - ptx_info_t *s; - for ( s=g_ptx_source_array; s!=NULL; s=s->next ) { - gpgpu_ptx_sim_load_ptx_from_string(s->str, ++source_num); - load_static_globals(g_global_symbol_table,STATIC_ALLOC_LIMIT,0xFFFFFFFF); - load_constants(g_global_symbol_table,STATIC_ALLOC_LIMIT); - } - } else { - g_filename = NULL; - struct dirent **namelist; - int n; - - n = scandir(".", &namelist, ptx_file_filter, alphasort); - if (n < 0) - perror("scandir"); - else { - while (n--) { - if ( g_filename != NULL ) { - printf("Loader error: support for multiple .ptx files not yet enabled\n"); - abort(); - } - g_filename = strdup(namelist[n]->d_name); - printf("Parsing %s..\n", g_filename); - ptx_in = fopen( g_filename, "r" ); - free(namelist[n]); - init_parser(); - ptx_parse (); - ptxinfo_in = open_ptxinfo(g_filename); - ptxinfo_parse(); - g_filename = NULL; - load_static_globals(g_global_symbol_table,STATIC_ALLOC_LIMIT,0xFFFFFFFF); - load_constants(g_global_symbol_table,STATIC_ALLOC_LIMIT); - } - free(namelist); - } - } - } - - if ( ptx_in == NULL && g_override_embedded_ptx ) { - printf("GPGPU-Sim PTX Simulator error: Could find/open .ptx file for reading\n"); - printf(" This means there are no .ptx files in the current directory.\n"); - printf(" Either place a .ptx file in the current directory, or ensure\n" ); - printf(" the PTX_SIM_KERNELFILE environment variable points to .ptx file.\n"); - printf(" PTX_SIM_KERNELFILE=\"%s\"\n", g_filename ); - exit(1); - } - - if ( g_error_detected ) { - printf( "GPGPU-Sim PTX: Program parsing completed: Errors detected.\n" ); - exit(1); - } else { - printf( "GPGPU-Sim PTX: Program parsing completed (max %u registers used per thread).\n", g_max_regs_per_thread ); - } - - if ( g_kernel_name_to_function_lookup ) { - for ( std::map<std::string,function_info*>::iterator f=g_kernel_name_to_function_lookup->begin(); - f != g_kernel_name_to_function_lookup->end(); f++ ) { - gpgpu_ptx_assemble(f->first,f->second); - } - } -} extern time_t simulation_starttime; diff --git a/src/cuda-sim/cuda-sim.h b/src/cuda-sim/cuda-sim.h index 25b0cb2..2e67e15 100644 --- a/src/cuda-sim/cuda-sim.h +++ b/src/cuda-sim/cuda-sim.h @@ -3,12 +3,23 @@ #include "../abstract_hardware_model.h" #include <stdlib.h> +#include <map> +#include <string> class memory_space; +class function_info; +class symbol_table; extern const char *g_gpgpusim_version_string; extern int g_ptx_sim_mode; extern memory_space *g_global_mem; +extern int g_debug_execution; +extern int g_debug_thread_uid; +extern unsigned g_max_regs_per_thread; +extern bool g_debug_ir_generation; +extern const char *g_filename; +extern std::map<std::string,function_info*> *g_kernel_name_to_function_lookup; +extern std::map<std::string,symbol_table*> g_kernel_name_to_symtab_lookup; extern void gpgpu_ptx_sim_add_ptxstring( const char *ptx, const char *source_fname ); extern void gpgpu_ptx_sim_main_func( const char *kernel_key, dim3 gridDim, dim3 blockDim, struct gpgpu_ptx_sim_arg *); @@ -30,5 +41,6 @@ extern void gpgpu_ptx_sim_bindNameToTexture(const char* name, const struct tex extern int gpgpu_ptx_sim_sizeofTexture(const char* name); extern const char* gpgpu_ptx_sim_findNamefromTexture(const struct textureReference* texref); extern const struct textureReference* gpgpu_ptx_sim_accessTextureofName(const char* name); +extern void read_sim_environment_variables(); #endif diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index d663d0a..b3a0342 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -74,6 +74,8 @@ #include "cuda-math.h" #include "../abstract_hardware_model.h" +#include "ptx_loader.h" + #include <stdarg.h> unsigned g_num_ptx_inst_uid=0; @@ -90,11 +92,6 @@ extern std::map<struct textureReference*,struct cudaArray*> TextureToArrayMap; / extern std::map<struct textureReference*,struct textureInfo*> TextureToInfoMap; // texture bindings extern std::map<std::string, struct textureReference*> NameToTextureMap; -memory_space *g_global_mem; -memory_space *g_tex_mem; -memory_space *g_surf_mem; -memory_space *g_param_mem; - void inst_not_implemented( const ptx_instruction * pI ) ; unsigned unfound_register_warned = 0; diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc index d049a6a..51ad05f 100644 --- a/src/cuda-sim/ptx_ir.cc +++ b/src/cuda-sim/ptx_ir.cc @@ -72,16 +72,17 @@ #include <stdarg.h> #include "cuda-sim.h" +#include "../option_parser.h" -extern unsigned g_max_regs_per_thread; extern "C" int ptx_error( const char *s ); +extern int ptx_lineno; // the program intermediate representation... symbol_table *g_global_symbol_table = NULL; -static symbol_table *g_current_symbol_table = NULL; -std::list<ptx_instruction*> g_instructions; -symbol *g_last_symbol = NULL; std::map<std::string,symbol_table*> g_sym_name_to_symbol_table; +static symbol_table *g_current_symbol_table = NULL; +static std::list<ptx_instruction*> g_instructions; +static symbol *g_last_symbol = NULL; int g_error_detected = 0; @@ -104,13 +105,6 @@ std::list<operand_info> g_operands; std::list<int> g_options; std::list<int> g_scalar_type; -extern bool g_debug_ir_generation; -extern const char *g_filename; -extern int ptx_lineno; -extern int g_debug_execution; -extern int g_debug_thread_uid; - - #define DPRINTF(...) \ if( g_debug_ir_generation ) { \ printf(" %s:%u => ",g_filename,ptx_lineno); \ @@ -212,8 +206,6 @@ void add_directive() #define mymax(a,b) ((a)>(b)?(a):(b)) -void gpgpu_ptx_assemble( std::string kname, void *kinfo ); - void end_function() { DPRINTF("end_function"); @@ -229,9 +221,6 @@ void end_function() DPRINTF("function %s, PC = %d\n", g_func_info->get_name().c_str(), g_func_info->get_start_PC()); } -extern int ptx_lineno; -extern const char *g_filename; - #define parse_error(msg, ...) parse_error_impl(__FILE__,__LINE__, msg, ##__VA_ARGS__) #define parse_assert(cond,msg, ...) parse_assert_impl((cond),__FILE__,__LINE__, msg, ##__VA_ARGS__) @@ -1680,3 +1669,154 @@ void function_info::print_insn( unsigned pc, FILE * fp ) const } } +static int g_save_embedded_ptx = 0; + +extern "C" int ptx_parse(); +extern "C" int ptx__scan_string(const char*); +extern "C" FILE *ptx_in; + +extern "C" const char *g_ptxinfo_filename; +extern "C" int ptxinfo_parse(); +extern "C" int ptxinfo_debug; +extern "C" FILE *ptxinfo_in; + +static void print_ptx_file( const char *p, unsigned source_num, const char *filename ); + +void ptx_reg_options(option_parser_t opp) +{ + option_parser_register(opp, "-save_embedded_ptx", OPT_BOOL, &g_save_embedded_ptx, + "saves ptx files embedded in binary as <n>.ptx", + "0"); +} + +void gpgpu_ptx_sim_load_ptx_from_string( const char *p, unsigned source_num ) +{ + char buf[1024]; + snprintf(buf,1024,"_%u.ptx", source_num ); + if( g_save_embedded_ptx ) { + FILE *fp = fopen(buf,"w"); + fprintf(fp,"%s",p); + fclose(fp); + } + g_filename = strdup(buf); + init_parser(); + ptx__scan_string(p); + int errors = ptx_parse (); + if ( errors ) { + char fname[1024]; + snprintf(fname,1024,"_ptx_XXXXXX"); + int fd=mkstemp(fname); + close(fd); + printf("GPGPU-Sim PTX: parser error detected, exiting... but first extracting .ptx to \"%s\"\n", fname); + FILE *ptxfile = fopen(fname,"w"); + fprintf(ptxfile,"%s", p ); + fclose(ptxfile); + abort(); + exit(40); + } + + if ( g_debug_execution >= 100 ) + print_ptx_file(p,source_num,g_filename); + + printf("GPGPU-Sim PTX: finished parsing EMBEDDED .ptx file %s\n",g_filename); + + char fname[1024]; + snprintf(fname,1024,"_ptx_XXXXXX"); + int fd=mkstemp(fname); + close(fd); + + printf("GPGPU-Sim PTX: extracting embedded .ptx to temporary file \"%s\"\n", fname); + FILE *ptxfile = fopen(fname,"w"); + fprintf(ptxfile,"%s",p); + fclose(ptxfile); + + char fname2[1024]; + snprintf(fname2,1024,"_ptx2_XXXXXX"); + fd=mkstemp(fname2); + close(fd); + char commandline2[4096]; + snprintf(commandline2,4096,"cat %s | sed 's/.version 1.5/.version 1.4/' | sed 's/, texmode_independent//' | sed 's/\\(\\.extern \\.const\\[1\\] .b8 \\w\\+\\)\\[\\]/\\1\\[1\\]/' | sed 's/const\\[.\\]/const\\[0\\]/g' > %s", fname, fname2); + int result = system(commandline2); + if( result != 0 ) { + printf("GPGPU-Sim PTX: ERROR ** while loading PTX (a) %d\n", result); + printf(" Ensure you have write access to simulation directory\n"); + printf(" and have \'cat\' and \'sed\' in your path.\n"); + exit(1); + } + + char tempfile_ptxinfo[1024]; + snprintf(tempfile_ptxinfo,1024,"%sinfo",fname); + char commandline[1024]; + char extra_flags[1024]; + extra_flags[0]=0; +#if CUDART_VERSION >= 3000 + snprintf(extra_flags,1024,"--gpu-name=sm_20"); +#endif + snprintf(commandline,1024,"ptxas %s -v %s --output-file /dev/null 2> %s", + extra_flags, fname2, tempfile_ptxinfo); + printf("GPGPU-Sim PTX: generating ptxinfo using \"%s\"\n", commandline); + result = system(commandline); + if( result != 0 ) { + printf("GPGPU-Sim PTX: ERROR ** while loading PTX (b) %d\n", result); + printf(" Ensure ptxas is in your path.\n"); + exit(1); + } + + ptxinfo_in = fopen(tempfile_ptxinfo,"r"); + g_ptxinfo_filename = tempfile_ptxinfo; + ptxinfo_parse(); + snprintf(commandline,1024,"rm -f %s %s %s", fname, fname2, tempfile_ptxinfo); + printf("GPGPU-Sim PTX: removing ptxinfo using \"%s\"\n", commandline); + result = system(commandline); + if( result != 0 ) { + printf("GPGPU-Sim PTX: ERROR ** while loading PTX (c) %d\n", result); + exit(1); + } + g_filename = NULL; +} + + +const ptx_instruction *ptx_instruction_lookup( const char *filename, unsigned linenumber ); + +void print_ptx_file( const char *p, unsigned source_num, const char *filename ) +{ + printf("\nGPGPU-Sim PTX: file _%u.ptx contents:\n\n", source_num ); + char *s = strdup(p); + char *t = s; + unsigned n=1; + while ( *t != '\0' ) { + char *u = t; + while ( (*u != '\n') && (*u != '\0') ) u++; + unsigned last = (*u == '\0'); + *u = '\0'; + const ptx_instruction *pI = ptx_instruction_lookup(filename,n); + char pc[64]; + if( pI && pI->get_PC() ) + snprintf(pc,64,"%4u", pI->get_PC() ); + else + snprintf(pc,64," "); + printf(" _%u.ptx %4u (pc=%s): %s\n", source_num, n, pc, t ); + if ( last ) break; + t = u+1; + n++; + } + free(s); + fflush(stdout); +} + +void gpgpu_ptx_assemble( std::string kname, void *kinfo ) +{ + function_info *func_info = (function_info *)kinfo; + if( func_info->is_extern() ) { + printf("GPGPU-Sim PTX: skipping assembly for extern declared function \'%s\'\n", func_info->get_name().c_str() ); + return; + } + if( g_kernel_name_to_symtab_lookup[ kname ] == NULL ) { + printf("\nGPGPU-Sim PTX: ERROR no information for kernel \'%s\'\n" + " this can happen for kernels contained in CUDA\n" + " libraries (such as CUBLAS, CUFFT, or CUDPP)\n", kname.c_str() ); + exit(1); + } + g_func_info = func_info; + func_info->ptx_assemble(); +} diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h index 839cceb..4600be5 100644 --- a/src/cuda-sim/ptx_ir.h +++ b/src/cuda-sim/ptx_ir.h @@ -1257,12 +1257,31 @@ struct textureInfo { extern function_info *g_func_info; extern int g_error_detected; -extern bool g_debug_ir_generation; -extern std::list<ptx_instruction*> g_instructions; extern symbol_table *g_entrypoint_symbol_table; extern function_info *g_entrypoint_func_info; extern symbol_table *g_global_symbol_table; +extern std::map<std::string,symbol_table*> g_sym_name_to_symbol_table; void init_parser(); +#define GLOBAL_HEAP_START 0x10000000 + // start allocating from this address (lower values used for allocating globals in .ptx file) + +#define SHARED_MEM_SIZE_MAX (64*1024) +#define LOCAL_MEM_SIZE_MAX 1024 +#define MAX_STREAMING_MULTIPROCESSORS 64 +#define MAX_THREAD_PER_SM 1024 +#define TOTAL_LOCAL_MEM_PER_SM (MAX_THREAD_PER_SM*LOCAL_MEM_SIZE_MAX) +#define TOTAL_SHARED_MEM (MAX_STREAMING_MULTIPROCESSORS*SHARED_MEM_SIZE_MAX) +#define TOTAL_LOCAL_MEM (MAX_STREAMING_MULTIPROCESSORS*MAX_THREAD_PER_SM*LOCAL_MEM_SIZE_MAX) +#define SHARED_GENERIC_START (GLOBAL_HEAP_START-TOTAL_SHARED_MEM) +#define LOCAL_GENERIC_START (SHARED_GENERIC_START-TOTAL_LOCAL_MEM) + +#define STATIC_ALLOC_LIMIT (GLOBAL_HEAP_START - (TOTAL_LOCAL_MEM+TOTAL_SHARED_MEM)) + +void gpgpu_ptx_sim_load_ptx_from_string( const char *p, unsigned source_num ); +void gpgpu_ptx_assemble( std::string kname, void *kinfo ); +#include "../option_parser.h" +void ptx_reg_options(option_parser_t opp); + extern "C" { #endif diff --git a/src/cuda-sim/ptx_loader.cc b/src/cuda-sim/ptx_loader.cc new file mode 100644 index 0000000..8c13f6d --- /dev/null +++ b/src/cuda-sim/ptx_loader.cc @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2009 by Tor M. Aamodt, Wilson W. L. Fung, Ali Bakhoda, + * George L. Yuan, Dan O'Connor, Joey Ting, Henry Wong and the + * University of British Columbia + * Vancouver, BC V6T 1Z4 + * All Rights Reserved. + * + * THIS IS A LEGAL DOCUMENT BY DOWNLOADING GPGPU-SIM, YOU ARE AGREEING TO THESE + * TERMS AND CONDITIONS. + * + * 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 OWNERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, 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. + * + * NOTE: The files libcuda/cuda_runtime_api.c and src/cuda-sim/cuda-math.h + * are derived from the CUDA Toolset available from http://www.nvidia.com/cuda + * (property of NVIDIA). The files benchmarks/BlackScholes/ and + * benchmarks/template/ are derived from the CUDA SDK available from + * http://www.nvidia.com/cuda (also property of NVIDIA). The files from + * src/intersim/ are derived from Booksim (a simulator provided with the + * textbook "Principles and Practices of Interconnection Networks" available + * from http://cva.stanford.edu/books/ppin/). As such, those files are bound by + * the corresponding legal terms and conditions set forth separately (original + * copyright notices are left in files from these sources and where we have + * modified a file our copyright notice appears before the original copyright + * notice). + * + * Using this version of GPGPU-Sim requires a complete installation of CUDA + * which is distributed seperately by NVIDIA under separate terms and + * conditions. To use this version of GPGPU-Sim with OpenCL requires a + * recent version of NVIDIA's drivers which support OpenCL. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 3. 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. + * + * 4. This version of GPGPU-SIM is distributed freely for non-commercial use only. + * + * 5. No nonprofit user may place any restrictions on the use of this software, + * including as modified by the user, by any other authorized user. + * + * 6. GPGPU-SIM was developed primarily by Tor M. Aamodt, Wilson W. L. Fung, + * Ali Bakhoda, George L. Yuan, at the University of British Columbia, + * Vancouver, BC V6T 1Z4 + */ + +#include "ptx_loader.h" +#include "ptx_ir.h" +#include "cuda-sim.h" +#include <dirent.h> + +/// globals + +memory_space *g_global_mem; +memory_space *g_tex_mem; +memory_space *g_surf_mem; +memory_space *g_param_mem; +bool g_override_embedded_ptx = false; + +struct ptx_info_t { + char *str; + char *fname; + ptx_info_t *next; +}; + +/// extern prototypes + +extern "C" int ptx_parse(); +extern "C" int ptx__scan_string(const char*); +extern "C" FILE *ptx_in; + +extern "C" const char *g_ptxinfo_filename = NULL; +extern "C" int ptxinfo_parse(); +extern "C" int ptxinfo_debug; +extern "C" FILE *ptxinfo_in; + +/// static functions + +static int load_static_globals( symbol_table *symtab, unsigned min_gaddr, unsigned max_gaddr) +{ + printf( "GPGPU-Sim PTX: loading globals with explicit initializers... \n" ); + fflush(stdout); + int ng_bytes=0; + symbol_table::iterator g=symtab->global_iterator_begin(); + + for ( ; g!=symtab->global_iterator_end(); g++) { + symbol *global = *g; + if ( global->has_initializer() ) { + printf( "GPGPU-Sim PTX: initializing '%s' ... ", global->name().c_str() ); + unsigned addr=global->get_address(); + const type_info *type = global->type(); + type_info_key ti=type->get_key(); + size_t size; + int t; + ti.type_decode(size,t); + int nbytes = size/8; + int offset=0; + std::list<operand_info> init_list = global->get_initializer(); + for ( std::list<operand_info>::iterator i=init_list.begin(); i!=init_list.end(); i++ ) { + operand_info op = *i; + ptx_reg_t value = op.get_literal_value(); + assert( (addr+offset+nbytes) < min_gaddr ); // min_gaddr is start of "heap" for cudaMalloc + g_global_mem->write(addr+offset,nbytes,&value,NULL,NULL); // assuming little endian here + offset+=nbytes; + ng_bytes+=nbytes; + } + printf(" wrote %u bytes\n", offset ); + } + } + printf( "GPGPU-Sim PTX: finished loading globals (%u bytes total).\n", ng_bytes ); + fflush(stdout); + return ng_bytes; +} + +static int load_constants( symbol_table *symtab, addr_t min_gaddr ) +{ + printf( "GPGPU-Sim PTX: loading constants with explicit initializers... " ); + fflush(stdout); + int nc_bytes = 0; + symbol_table::iterator g=symtab->const_iterator_begin(); + + for ( ; g!=symtab->const_iterator_end(); g++) { + symbol *constant = *g; + if ( constant->is_const() && constant->has_initializer() ) { + + // get the constant element data size + int basic_type; + size_t num_bits; + constant->type()->get_key().type_decode(num_bits,basic_type); + + std::list<operand_info> init_list = constant->get_initializer(); + int nbytes_written = 0; + for ( std::list<operand_info>::iterator i=init_list.begin(); i!=init_list.end(); i++ ) { + operand_info op = *i; + ptx_reg_t value = op.get_literal_value(); + int nbytes = num_bits/8; + switch ( op.get_type() ) { + case int_t: assert(nbytes >= 1); break; + case float_op_t: assert(nbytes == 4); break; + case double_op_t: assert(nbytes >= 4); break; // account for double DEMOTING + default: + abort(); + } + unsigned addr=constant->get_address() + nbytes_written; + assert( addr+nbytes < min_gaddr ); + + g_global_mem->write(addr,nbytes,&value,NULL,NULL); // assume little endian (so u8 is the first byte in u32) + nc_bytes+=nbytes; + nbytes_written += nbytes; + } + } + } + printf( " done.\n"); + fflush(stdout); + return nc_bytes; +} + +static FILE *open_ptxinfo (const char* ptx_filename) +{ + const int ptx_fnamelen = strlen(ptx_filename); + char *ptxi_fname = new char[ptx_fnamelen+5]; + strcpy (ptxi_fname, ptx_filename); + strcpy (ptxi_fname+ptx_fnamelen, "info"); + + //ptxinfo_debug=1; + g_ptxinfo_filename = ptxi_fname; + FILE *f = fopen (ptxi_fname, "rt"); + return f; +} + +static int ptx_file_filter( +#if !defined(__APPLE__) + const +#endif + struct dirent *de ) +{ + const char *tmp = strstr(de->d_name,".ptx"); + if ( tmp != NULL && tmp[4] == 0 ) { + return 1; + } + return 0; +} + +// global functions + +static ptx_info_t *g_ptx_source_array = NULL; + +void gpgpu_ptx_sim_load_gpu_kernels() +{ + static unsigned source_num = 0; + ptx_in = NULL; + if ( g_filename ) + ptx_in = fopen( g_filename, "r" ); + gpgpu_ptx_sim_init_memory(); + if (ptx_in) { + init_parser(); + ptx_parse(); + ptxinfo_in = open_ptxinfo(g_filename); + ptxinfo_parse(); + load_static_globals(g_global_symbol_table,STATIC_ALLOC_LIMIT,0xFFFFFFFF); + load_constants(g_global_symbol_table,STATIC_ALLOC_LIMIT); + } else { + if (!g_override_embedded_ptx) { + printf("GPGPU-Sim PTX: USING EMBEDDED .ptx files...\n"); + ptx_info_t *s; + for ( s=g_ptx_source_array; s!=NULL; s=s->next ) { + gpgpu_ptx_sim_load_ptx_from_string(s->str, ++source_num); + load_static_globals(g_global_symbol_table,STATIC_ALLOC_LIMIT,0xFFFFFFFF); + load_constants(g_global_symbol_table,STATIC_ALLOC_LIMIT); + } + } else { + g_filename = NULL; + struct dirent **namelist; + int n; + + n = scandir(".", &namelist, ptx_file_filter, alphasort); + if (n < 0) + perror("scandir"); + else { + while (n--) { + if ( g_filename != NULL ) { + printf("Loader error: support for multiple .ptx files not yet enabled\n"); + abort(); + } + g_filename = strdup(namelist[n]->d_name); + printf("Parsing %s..\n", g_filename); + ptx_in = fopen( g_filename, "r" ); + free(namelist[n]); + init_parser(); + ptx_parse (); + ptxinfo_in = open_ptxinfo(g_filename); + ptxinfo_parse(); + g_filename = NULL; + load_static_globals(g_global_symbol_table,STATIC_ALLOC_LIMIT,0xFFFFFFFF); + load_constants(g_global_symbol_table,STATIC_ALLOC_LIMIT); + } + free(namelist); + } + } + } + + if ( ptx_in == NULL && g_override_embedded_ptx ) { + printf("GPGPU-Sim PTX Simulator error: Could find/open .ptx file for reading\n"); + printf(" This means there are no .ptx files in the current directory.\n"); + printf(" Either place a .ptx file in the current directory, or ensure\n" ); + printf(" the PTX_SIM_KERNELFILE environment variable points to .ptx file.\n"); + printf(" PTX_SIM_KERNELFILE=\"%s\"\n", g_filename ); + exit(1); + } + + if ( g_error_detected ) { + printf( "GPGPU-Sim PTX: Program parsing completed: Errors detected.\n" ); + exit(1); + } else { + printf( "GPGPU-Sim PTX: Program parsing completed (max %u registers used per thread).\n", g_max_regs_per_thread ); + } + + if ( g_kernel_name_to_function_lookup ) { + for ( std::map<std::string,function_info*>::iterator f=g_kernel_name_to_function_lookup->begin(); + f != g_kernel_name_to_function_lookup->end(); f++ ) { + gpgpu_ptx_assemble(f->first,f->second); + } + } +} + +void gpgpu_ptx_sim_add_ptxstring( const char *ptx_string, const char *sourcefname ) +{ + ptx_info_t *t = new ptx_info_t; + t->next = NULL; + t->str = strdup(ptx_string); + t->fname = strdup(sourcefname); + + // put ptx source into a fifo + if (g_ptx_source_array == NULL) { + // first ptx source + g_ptx_source_array = t; + } else { + // insert subsequent ptx source at the end of queue + ptx_info_t *l_ptx_source = g_ptx_source_array; + while (l_ptx_source->next != NULL) { + l_ptx_source = l_ptx_source->next; + } + l_ptx_source->next = t; + } +} diff --git a/src/cuda-sim/ptx_loader.h b/src/cuda-sim/ptx_loader.h new file mode 100644 index 0000000..33c6dc9 --- /dev/null +++ b/src/cuda-sim/ptx_loader.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2009 by Tor M. Aamodt, Wilson W. L. Fung, Ali Bakhoda, + * George L. Yuan, Dan O'Connor, Joey Ting, Henry Wong and the + * University of British Columbia + * Vancouver, BC V6T 1Z4 + * All Rights Reserved. + * + * THIS IS A LEGAL DOCUMENT BY DOWNLOADING GPGPU-SIM, YOU ARE AGREEING TO THESE + * TERMS AND CONDITIONS. + * + * 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 OWNERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, 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. + * + * NOTE: The files libcuda/cuda_runtime_api.c and src/cuda-sim/cuda-math.h + * are derived from the CUDA Toolset available from http://www.nvidia.com/cuda + * (property of NVIDIA). The files benchmarks/BlackScholes/ and + * benchmarks/template/ are derived from the CUDA SDK available from + * http://www.nvidia.com/cuda (also property of NVIDIA). The files from + * src/intersim/ are derived from Booksim (a simulator provided with the + * textbook "Principles and Practices of Interconnection Networks" available + * from http://cva.stanford.edu/books/ppin/). As such, those files are bound by + * the corresponding legal terms and conditions set forth separately (original + * copyright notices are left in files from these sources and where we have + * modified a file our copyright notice appears before the original copyright + * notice). + * + * Using this version of GPGPU-Sim requires a complete installation of CUDA + * which is distributed seperately by NVIDIA under separate terms and + * conditions. To use this version of GPGPU-Sim with OpenCL requires a + * recent version of NVIDIA's drivers which support OpenCL. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 3. 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. + * + * 4. This version of GPGPU-SIM is distributed freely for non-commercial use only. + * + * 5. No nonprofit user may place any restrictions on the use of this software, + * including as modified by the user, by any other authorized user. + * + * 6. GPGPU-SIM was developed primarily by Tor M. Aamodt, Wilson W. L. Fung, + * Ali Bakhoda, George L. Yuan, at the University of British Columbia, + * Vancouver, BC V6T 1Z4 + */ + + +#ifndef PTX_LOADER_H_INCLUDED +#define PTX_LOADER_H_INCLUDED + +class memory_space; + +extern memory_space *g_global_mem; +extern memory_space *g_tex_mem; +extern memory_space *g_surf_mem; +extern memory_space *g_param_mem; +extern bool g_override_embedded_ptx; + +void gpgpu_ptx_sim_load_gpu_kernels(); +void gpgpu_ptx_sim_add_ptxstring( const char *ptx_string, const char *sourcefname ); + +#endif |
