/* * Copyright (c) 2009 by Tor M. Aamodt, Wilson W. L. Fung, Ali Bakhoda, * George L. Yuan 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_parser.h" #include "ptx_ir.h" #include extern "C" int ptx_error( const char *s ); extern int ptx_lineno; static unsigned g_warp_size; void set_ptx_warp_size(unsigned warp_size) { g_warp_size=warp_size; } static bool g_debug_ir_generation=false; const char *g_filename; unsigned g_max_regs_per_thread = 0; // the program intermediate representation... static symbol_table *g_global_symbol_table = NULL; std::map g_sym_name_to_symbol_table; static symbol_table *g_current_symbol_table = NULL; static std::list g_instructions; static symbol *g_last_symbol = NULL; int g_error_detected = 0; // type specifier stuff: memory_space_t g_space_spec = undefined_space; int g_scalar_type_spec = -1; int g_vector_spec = -1; int g_alignment_spec = -1; int g_extern_spec = 0; // variable declaration stuff: type_info *g_var_type = NULL; // instruction definition stuff: const symbol *g_pred; int g_neg_pred; int g_pred_mod; symbol *g_label; int g_opcode = -1; std::list g_operands; std::list g_options; std::list g_scalar_type; #define DPRINTF(...) \ if( g_debug_ir_generation ) { \ printf(" %s:%u => ",g_filename,ptx_lineno); \ printf(" (%s:%u) ", __FILE__, __LINE__); \ printf(__VA_ARGS__); \ printf("\n"); \ fflush(stdout); \ } static unsigned g_entry_func_param_index=0; static function_info *g_func_info = NULL; static std::map g_ptx_token_decode; static operand_info g_return_var; const char *decode_token( int type ) { return g_ptx_token_decode[type].c_str(); } void read_parser_environment_variables() { g_filename = getenv("PTX_SIM_KERNELFILE"); char *dbg_level = getenv("PTX_SIM_DEBUG"); if ( dbg_level && strlen(dbg_level) ) { int debug_execution=0; sscanf(dbg_level,"%d", &debug_execution); if ( debug_execution >= 30 ) g_debug_ir_generation=true; } } symbol_table *init_parser( const char *ptx_filename ) { g_filename = strdup(ptx_filename); g_global_symbol_table = g_current_symbol_table = new symbol_table("global",0,NULL); ptx_lineno = 1; #define DEF(X,Y) g_ptx_token_decode[X] = Y; #include "ptx_parser_decode.def" #undef DEF return g_global_symbol_table; } void init_directive_state() { DPRINTF("init_directive_state"); g_space_spec=undefined_space; g_scalar_type_spec=-1; g_vector_spec=-1; g_opcode=-1; g_alignment_spec = -1; g_extern_spec = 0; g_scalar_type.clear(); g_operands.clear(); g_last_symbol = NULL; } void init_instruction_state() { DPRINTF("init_instruction_state"); g_pred = NULL; g_neg_pred = 0; g_pred_mod = -1; g_label = NULL; g_opcode = -1; g_options.clear(); g_return_var = operand_info(); init_directive_state(); } static int g_entry_point; void start_function( int entry_point ) { DPRINTF("start_function"); init_directive_state(); init_instruction_state(); g_entry_point = entry_point; g_func_info = NULL; g_entry_func_param_index=0; } char *g_add_identifier_cached__identifier = NULL; int g_add_identifier_cached__array_dim; int g_add_identifier_cached__array_ident; void add_function_name( const char *name ) { DPRINTF("add_function_name %s %s", name, ((g_entry_point==1)?"(entrypoint)":((g_entry_point==2)?"(extern)":""))); bool prior_decl = g_global_symbol_table->add_function_decl( name, g_entry_point, &g_func_info, &g_current_symbol_table ); if( g_add_identifier_cached__identifier ) { add_identifier( g_add_identifier_cached__identifier, g_add_identifier_cached__array_dim, g_add_identifier_cached__array_ident ); free( g_add_identifier_cached__identifier ); g_add_identifier_cached__identifier = NULL; g_func_info->add_return_var( g_last_symbol ); init_directive_state(); } if( prior_decl ) { g_func_info->remove_args(); } g_global_symbol_table->add_function( g_func_info, g_filename, ptx_lineno ); } void add_directive() { DPRINTF("add_directive"); init_directive_state(); } #define mymax(a,b) ((a)>(b)?(a):(b)) void end_function() { DPRINTF("end_function"); init_directive_state(); init_instruction_state(); g_max_regs_per_thread = mymax( g_max_regs_per_thread, (g_current_symbol_table->next_reg_num()-1)); g_func_info->add_inst( g_instructions ); g_instructions.clear(); gpgpu_ptx_assemble( g_func_info->get_name(), g_func_info ); g_current_symbol_table = g_global_symbol_table; DPRINTF("function %s, PC = %d\n", g_func_info->get_name().c_str(), g_func_info->get_start_PC()); } #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__) void parse_error_impl( const char *file, unsigned line, const char *msg, ... ) { va_list ap; char buf[1024]; va_start(ap,msg); vsnprintf(buf,1024,msg,ap); va_end(ap); g_error_detected = 1; printf("%s:%u: Parse error: %s (%s:%u)\n\n", g_filename, ptx_lineno, buf, file, line); ptx_error(NULL); abort(); exit(1); } void parse_assert_impl( int test_value, const char *file, unsigned line, const char *msg, ... ) { va_list ap; char buf[1024]; va_start(ap,msg); vsnprintf(buf,1024,msg,ap); va_end(ap); if ( test_value == 0 ) parse_error_impl(file,line, msg); } extern "C" char linebuf[1024]; void set_return() { parse_assert( (g_opcode == CALL_OP || g_opcode == CALLP_OP), "only call can have return value"); g_operands.front().set_return(); g_return_var = g_operands.front(); } std::map > g_inst_lookup; const ptx_instruction *ptx_instruction_lookup( const char *filename, unsigned linenumber ) { std::map >::iterator f=g_inst_lookup.find(filename); if( f == g_inst_lookup.end() ) return NULL; std::map::iterator l=f->second.find(linenumber); if( l == f->second.end() ) return NULL; return l->second; } void add_instruction() { DPRINTF("add_instruction: %s", ((g_opcode>0)?g_opcode_string[g_opcode]:"