diff options
| author | Tor Aamodt <[email protected]> | 2010-07-15 18:09:46 -0800 |
|---|---|---|
| committer | Tor Aamodt <[email protected]> | 2010-07-15 18:09:46 -0800 |
| commit | 69f2911e04ffb1b19eef1fafb8c040af271f656e (patch) | |
| tree | 231d3b6bdc3a202f7c255bfcf7bf2c36e32cee9e /src/cuda-sim/ptx_ir.h | |
creating branch for adding support for CUDA 3.x and Fermi
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 6829]
Diffstat (limited to 'src/cuda-sim/ptx_ir.h')
| -rw-r--r-- | src/cuda-sim/ptx_ir.h | 1223 |
1 files changed, 1223 insertions, 0 deletions
diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h new file mode 100644 index 0000000..82d5b4c --- /dev/null +++ b/src/cuda-sim/ptx_ir.h @@ -0,0 +1,1223 @@ +/* + * 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_ir_INCLUDED +#define ptx_ir_INCLUDED + +#ifdef __cplusplus + + #include <cstdlib> + #include <cstring> + #include <string> + #include <list> + #include <map> + #include <vector> + #include <assert.h> + + #include "ptx.tab.h" + #include "ptx_sim.h" + #include "dram_callback.h" + #include "../util.h" + + #include "memory.h" + +enum space_type { + undefined, inst_space +}; + + +class addr { /* need this because there are many distinct address spaces (global, local, param, tex, surf, shared) */ +public: + + addr() { m_space=undefined; m_addr = 0;} + void set_space( enum space_type space ); + operator unsigned() { return m_addr;} + +private: + enum space_type m_space; + unsigned m_addr; +}; + + +class type_info_key { +public: + type_info_key() + { + m_init = false; + } + type_info_key( int space_spec, int scalar_type_spec, int vector_spec, int alignment_spec, int extern_spec, int array_dim ) + { + m_init = true; + m_space_spec = space_spec; + m_scalar_type_spec = scalar_type_spec; + m_vector_spec = vector_spec; + m_alignment_spec = alignment_spec; + m_extern_spec = extern_spec; + m_array_dim = array_dim; + m_is_function = 0; + } + void set_is_func() + { + assert(!m_init); + m_init = true; + m_space_spec = 0; + m_scalar_type_spec = 0; + m_vector_spec = 0; + m_alignment_spec = 0; + m_extern_spec = 0; + m_array_dim = 0; + m_is_function = 1; + } + + void set_array_dim( int array_dim ) + { + m_array_dim = array_dim; + } + + bool is_reg() const { return m_space_spec == REG_DIRECTIVE;} + bool is_param() const { return m_space_spec == PARAM_DIRECTIVE;} + bool is_global() const { return m_space_spec == GLOBAL_DIRECTIVE;} + bool is_local() const { return m_space_spec == LOCAL_DIRECTIVE;} + bool is_shared() const { return m_space_spec == SHARED_DIRECTIVE;} + bool is_const() const { return m_space_spec == CONST_DIRECTIVE;} + bool is_tex() const { return m_space_spec == TEX_DIRECTIVE;} + bool is_func_addr() const { return m_is_function?true:false; } + int scalar_type() const { return m_scalar_type_spec;} +private: + bool m_init; + int m_space_spec; + int m_scalar_type_spec; + int m_vector_spec; + int m_alignment_spec; + int m_extern_spec; + int m_array_dim; + int m_is_function; + + friend class type_info_key_compare; +}; + +class symbol_table; + +struct type_info_key_compare { + bool operator()( const type_info_key &a, const type_info_key &b ) const + { + assert( a.m_init && b.m_init ); + if ( a.m_space_spec < b.m_space_spec ) return true; + if ( a.m_scalar_type_spec < b.m_scalar_type_spec ) return true; + if ( a.m_vector_spec < b.m_vector_spec ) return true; + if ( a.m_alignment_spec < b.m_alignment_spec ) return true; + if ( a.m_extern_spec < b.m_extern_spec ) return true; + if ( a.m_array_dim < b.m_array_dim ) return true; + if ( a.m_is_function < b.m_is_function ) return true; + + return false; + } +}; + +class type_info { +public: + type_info( symbol_table *scope, type_info_key t ) + { + m_type_info = t; + } + const type_info_key &get_key() const { return m_type_info;} + +private: + symbol_table *m_scope; + type_info_key m_type_info; +}; + +enum operand_type { + reg_t, vector_t, builtin_t, address_t, memory_t, float_op_t, double_op_t, int_t, + unsigned_t, symbolic_t, label_t, v_reg_t, v_float_op_t, v_double_op_t, + v_int_t, v_unsigned_t +}; + +class operand_info; + +class symbol { +public: + symbol( const char *name, const type_info *type, const char *location ) + { + m_uid = get_uid(); + m_name = name; + m_decl_location = location; + m_type = type; + m_address_valid = false; + m_is_label = false; + m_is_shared = false; + m_is_const = false; + m_is_global = false; + m_is_local = false; + m_is_tex = false; + m_is_func_addr = false; + m_reg_num_valid = false; + m_function = NULL; + if ( type ) m_is_shared = type->get_key().is_shared(); + if ( type ) m_is_const = type->get_key().is_const(); + if ( type ) m_is_global = type->get_key().is_global(); + if ( type ) m_is_local = type->get_key().is_local(); + if ( type ) m_is_tex = type->get_key().is_tex(); + if ( type ) m_is_func_addr = type->get_key().is_func_addr(); + } + const std::string &name() const { return m_name;} + const std::string &decl_location() const { return m_decl_location;} + const type_info *type() const { return m_type;} + addr_t get_address() const + { + assert( m_is_label || !m_type->get_key().is_reg() ); // todo : other assertions + assert( m_address_valid ); + return m_address; + } + function_info *get_pc() const + { + return m_function; + } + void set_regno( unsigned regno, unsigned arch_regno ) + { + m_reg_num_valid = true; + m_reg_num = regno; + m_arch_reg_num = arch_regno; + } + + void set_address( addr_t addr ) + { + m_address_valid = true; + m_address = addr; + } + void set_label_address( addr_t addr) + { + m_address_valid = true; + m_address = addr; + m_is_label = true; + } + void set_function( function_info *func ) + { + m_function = func; + m_is_func_addr = true; + } + + bool is_label() const { return m_is_label;} + bool is_shared() const { return m_is_shared;} + bool is_const() const { return m_is_const;} + bool is_global() const { return m_is_global;} + bool is_local() const { return m_is_local;} + bool is_tex() const { return m_is_tex;} + bool is_func_addr() const { return m_is_func_addr; } + + void add_initializer( const std::list<operand_info> &init ); + bool has_initializer() const + { + return m_initializer.size() > 0; + } + std::list<operand_info> get_initializer() const + { + return m_initializer; + } + unsigned reg_num() const + { + assert( m_reg_num_valid ); + return m_reg_num; + } + unsigned arch_reg_num() const + { + assert( m_reg_num_valid ); + return m_arch_reg_num; + } + void print_info(FILE *fp) const; + +private: + unsigned get_uid(); + unsigned m_uid; + const type_info *m_type; + std::string m_name; + std::string m_decl_location; + + unsigned m_address; + function_info *m_function; // used for function symbols + + bool m_address_valid; + bool m_is_label; + bool m_is_shared; + bool m_is_const; + bool m_is_global; + bool m_is_local; + bool m_is_tex; + bool m_is_func_addr; + unsigned m_reg_num; + unsigned m_arch_reg_num; + bool m_reg_num_valid; + + std::list<operand_info> m_initializer; + static unsigned sm_next_uid; +}; + + +class symbol_table { +public: + symbol_table(); + symbol_table( const char *scope_name, unsigned entry_point, symbol_table *parent ); + void set_name( const char *name ); + symbol* lookup( const char *identifier ); + std::string get_scope_name() const { return m_scope_name; } + symbol *add_variable( const char *identifier, const type_info *type, const char *filename, unsigned line ); + void add_function( function_info *func ); + bool add_function_decl( const char *name, int entry_point, function_info **func_info, symbol_table **symbol_table ); + type_info *add_type( int space_spec, int scalar_type_spec, int vector_spec, int alignment_spec, int extern_spec ); + type_info *add_type( function_info *func ); + type_info *get_array_type( type_info *base_type, unsigned array_dim ); + void set_label_address( const symbol *label, unsigned addr ); + unsigned next_reg_num() { return ++m_reg_allocator;} + addr_t get_shared_next() { return m_shared_next;} + addr_t get_global_next() { return m_global_next;} + addr_t get_local_next() { return m_local_next;} + addr_t get_tex_next() { return m_tex_next;} + void alloc_shared( unsigned num_bytes ) { m_shared_next += num_bytes;} + void alloc_global( unsigned num_bytes ) { m_global_next += num_bytes;} + void alloc_local( unsigned num_bytes ) { m_local_next += num_bytes;} + void alloc_tex( unsigned num_bytes ) { m_tex_next += num_bytes;} + + typedef std::list<symbol*>::iterator iterator; + + iterator param_iterator_begin() { return m_params.begin();} + iterator param_iterator_end() { return m_params.end();} + + iterator global_iterator_begin() { return m_globals.begin();} + iterator global_iterator_end() { return m_globals.end();} + + iterator const_iterator_begin() { return m_consts.begin();} + iterator const_iterator_end() { return m_consts.end();} + + void dump(); +private: + unsigned m_reg_allocator; + unsigned m_shared_next; + unsigned m_const_next; + unsigned m_global_next; + unsigned m_local_next; + unsigned m_tex_next; + + symbol_table *m_parent; + std::string m_scope_name; + std::map<std::string, symbol *> m_symbols; //map from name of register to pointers to the registers + std::map<type_info_key,type_info*,type_info_key_compare> m_types; + std::list<symbol*> m_params; + std::list<symbol*> m_globals; + std::list<symbol*> m_consts; + std::map<std::string,function_info*> m_function_info_lookup; + std::map<std::string,symbol_table*> m_function_symtab_lookup; +}; + +class operand_info { +public: + operand_info() + { + m_uid = get_uid(); + m_valid = false; + } + operand_info( const symbol *addr ) + { + m_uid = get_uid(); + m_valid = true; + if ( addr->is_label() ) { + m_type = label_t; + } else if ( addr->is_shared() ) { + m_type = symbolic_t; + } else if ( addr->is_const() ) { + m_type = symbolic_t; + } else if ( addr->is_global() ) { + m_type = symbolic_t; + } else if ( addr->is_local() ) { + m_type = symbolic_t; + } else if ( addr->is_tex() ) { + m_type = symbolic_t; + } else if ( addr->is_func_addr() ) { + m_type = symbolic_t; + } else { + m_type = reg_t; + } + m_value.m_symbolic = addr; + m_addr_offset = 0; + m_vector = false; + m_neg_pred = false; + m_is_return_var = false; + } + operand_info( int builtin_id, int dim_mod ) + { + m_uid = get_uid(); + m_valid = true; + m_vector = false; + m_type = builtin_t; + m_value.m_int = builtin_id; + m_addr_offset = dim_mod; + m_neg_pred = false; + m_is_return_var = false; + } + operand_info( const symbol *addr, int offset ) + { + m_uid = get_uid(); + m_valid = true; + m_vector = false; + m_type = address_t; + m_value.m_symbolic = addr; + m_addr_offset = offset; + m_neg_pred = false; + m_is_return_var = false; + } + operand_info( unsigned x ) + { + m_uid = get_uid(); + m_valid = true; + m_vector = false; + m_type = unsigned_t; + m_value.m_unsigned = x; + m_addr_offset = 0; + m_neg_pred = false; + m_is_return_var = false; + } + operand_info( int x ) + { + m_uid = get_uid(); + m_valid = true; + m_vector = false; + m_type = int_t; + m_value.m_int = x; + m_addr_offset = 0; + m_neg_pred = false; + m_is_return_var = false; + } + operand_info( float x ) + { + m_uid = get_uid(); + m_valid = true; + m_vector = false; + m_type = float_op_t; + m_value.m_float = x; + m_addr_offset = 0; + m_neg_pred = false; + m_is_return_var = false; + } + operand_info( double x ) + { + m_uid = get_uid(); + m_valid = true; + m_vector = false; + m_type = double_op_t; + m_value.m_double = x; + m_addr_offset = 0; + m_neg_pred = false; + m_is_return_var = false; + } + operand_info( const symbol *s1, const symbol *s2, const symbol *s3, const symbol *s4 ) + { + m_uid = get_uid(); + m_valid = true; + m_vector = true; + m_type = vector_t; + m_value.m_vector_symbolic = new const symbol*[4]; + m_value.m_vector_symbolic[0] = s1; + m_value.m_vector_symbolic[1] = s2; + m_value.m_vector_symbolic[2] = s3; + m_value.m_vector_symbolic[3] = s4; + m_addr_offset = 0; + m_neg_pred = false; + m_is_return_var = false; + } + + void make_memory_operand() { m_type = memory_t;} + void set_return() { m_is_return_var = true; } + + const std::string &name() const + { + assert( m_type == symbolic_t || m_type == reg_t || m_type == address_t || m_type == memory_t || m_type == label_t); + return m_value.m_symbolic->name(); + } + + unsigned get_vect_nelem() const + { + assert( is_vector() ); + if( !m_value.m_vector_symbolic[0] ) return 0; + if( !m_value.m_vector_symbolic[1] ) return 1; + if( !m_value.m_vector_symbolic[2] ) return 2; + if( !m_value.m_vector_symbolic[3] ) return 3; + return 4; + } + const std::string &vec_name1() const + { + assert( m_type == vector_t); + return m_value.m_vector_symbolic[0]->name(); + } + + const std::string &vec_name2() const + { + assert( m_type == vector_t); + return m_value.m_vector_symbolic[1]->name(); + } + + const std::string &vec_name3() const + { + assert( m_type == vector_t); + return m_value.m_vector_symbolic[2]->name(); + } + + const std::string &vec_name4() const + { + assert( m_type == vector_t); + return m_value.m_vector_symbolic[3]->name(); + } + + bool is_reg() const + { + if ( m_type == reg_t ) { + return true; + } + if ( m_type != symbolic_t ) { + return false; + } + return m_value.m_symbolic->type()->get_key().is_reg(); + } + + bool is_vector() const + { + if ( m_vector) return true; + return false; + } + int reg_num() const { return m_value.m_symbolic->reg_num();} + int reg1_num() const { return m_value.m_vector_symbolic[0]->reg_num();} + int reg2_num() const { return m_value.m_vector_symbolic[1]->reg_num();} + int reg3_num() const { return m_value.m_vector_symbolic[2]?m_value.m_vector_symbolic[2]->reg_num():0; } + int reg4_num() const { return m_value.m_vector_symbolic[3]?m_value.m_vector_symbolic[3]->reg_num():0; } + int arch_reg_num() const { return m_value.m_symbolic->arch_reg_num(); } + int arch_reg_num(unsigned n) const { return (m_value.m_vector_symbolic[n])? m_value.m_vector_symbolic[n]->arch_reg_num() : -1; } + bool is_label() const { return m_type == label_t;} + bool is_builtin() const { return m_type == builtin_t;} + bool is_memory_operand() const { return m_type == memory_t;} + bool is_literal() const { return m_type == int_t || + m_type == float_op_t || + m_type == double_op_t || + m_type == unsigned_t;} + bool is_shared() const { + if ( !(m_type == symbolic_t || m_type == address_t || m_type == memory_t) ) { + return false; + } + return m_value.m_symbolic->is_shared(); + } + bool is_const() const { return m_value.m_symbolic->is_const();} + bool is_global() const { return m_value.m_symbolic->is_global();} + bool is_local() const { return m_value.m_symbolic->is_local();} + bool is_tex() const { return m_value.m_symbolic->is_tex();} + bool is_return_var() const { return m_is_return_var; } + + bool is_function_address() const + { + if( m_type != symbolic_t ) { + return false; + } + return m_value.m_symbolic->is_func_addr(); + } + + ptx_reg_t get_literal_value() const + { + ptx_reg_t result; + switch ( m_type ) { + case int_t: result.s32 = m_value.m_int; break; + case float_op_t: result.f32 = m_value.m_float; break; + case double_op_t: result.f64 = m_value.m_double; break; + case unsigned_t: result.u32 = m_value.m_unsigned; break; + default: + assert(0); + break; + } + return result; + } + int get_int() const { return m_value.m_int;} + int get_addr_offset() const { return m_addr_offset;} + const symbol *get_symbol() const { return m_value.m_symbolic;} + void set_type( enum operand_type type ) + { + m_type = type; + } + enum operand_type get_type() const { + return m_type; + } + void set_neg_pred() + { + assert( m_valid ); + m_neg_pred = true; + } + bool is_neg_pred() const { return m_neg_pred; } + bool is_valid() const { return m_valid; } + +private: + unsigned m_uid; + bool m_valid; + bool m_vector; + enum operand_type m_type; + + union { + int m_int; + unsigned int m_unsigned; + float m_float; + double m_double; + int m_vint[4]; + unsigned int m_vunsigned[4]; + float m_vfloat[4]; + double m_vdouble[4]; + const symbol* m_symbolic; + const symbol** m_vector_symbolic; + } m_value; + + int m_addr_offset; + + bool m_neg_pred; + bool m_is_return_var; + + static unsigned sm_next_uid; + unsigned get_uid(); +}; + +extern const char *g_opcode_string[]; +extern unsigned g_num_ptx_inst_uid; +struct basic_block_t { + basic_block_t( unsigned ID, ptx_instruction *begin, ptx_instruction *end, bool entry, bool ex) + { + bb_id = ID; + ptx_begin = begin; + ptx_end = end; + is_entry=entry; + is_exit=ex; + immediatepostdominator_id = -1; + } + + ptx_instruction* ptx_begin; + ptx_instruction* ptx_end; + std::set<int> predecessor_ids; //indices of other basic blocks in m_basic_blocks array + std::set<int> successor_ids; + std::set<int> postdominator_ids; + std::set<int> dominator_ids; + std::set<int> Tmp_ids; + int immediatepostdominator_id; + bool is_entry; + bool is_exit; + unsigned bb_id; +}; + +struct gpgpu_recon_t { + address_type source_pc; + address_type target_pc; +}; + +class ptx_instruction { +public: + ptx_instruction( int opcode, + const symbol *pred, + int neg_pred, + symbol *label, + const std::list<operand_info> &operands, + const operand_info &return_var, + const std::list<int> &options, + const std::list<int> &scalar_type, + int space_spec, + const char *file, + unsigned line, + const char *source ); + + void print_insn() const; + void print_insn( FILE *fp ) const; + unsigned uid() const { return m_uid;} + int get_opcode() { return m_opcode;} + const char *get_opcode_cstr() const + { + if ( m_opcode != -1 ) { + return g_opcode_string[m_opcode]; + } else { + return "label"; + } + } + const char *source_file() const { return m_source_file.c_str();} + unsigned source_line() const { return m_source_line;} + unsigned get_num_operands() const { return m_operands.size();} + bool has_pred() const { return m_pred != NULL;} + operand_info get_pred() const { return operand_info( m_pred );} + bool get_pred_neg() const { return m_neg_pred;} + const char *get_source() const { return m_source.c_str();} + + typedef std::vector<operand_info>::const_iterator const_iterator; + + const_iterator op_iter_begin() const + { + return m_operands.begin(); + } + + const_iterator op_iter_end() const + { + return m_operands.end(); + } + + const operand_info &dst() const + { + assert( !m_operands.empty() ); + return m_operands[0]; + } + + const operand_info &func_addr() const + { + assert( !m_operands.empty() ); + if( !m_operands[0].is_return_var() ) { + return m_operands[0]; + } else { + assert( m_operands.size() >= 2 ); + return m_operands[1]; + } + } + + operand_info &dst() + { + assert( !m_operands.empty() ); + return m_operands[0]; + } + + const operand_info &src1() const + { + assert( m_operands.size() > 1 ); + return m_operands[1]; + } + + const operand_info &src2() const + { + assert( m_operands.size() > 2 ); + return m_operands[2]; + } + + const operand_info &src3() const + { + assert( m_operands.size() > 3 ); + return m_operands[3]; + } + + const operand_info &operand_lookup( unsigned n ) const + { + assert( n < m_operands.size() ); + return m_operands[n]; + } + bool has_return() const + { + return m_return_var.is_valid(); + } + + unsigned get_space() const { return m_space_spec;} + unsigned get_vector() const { return m_vector_spec;} + unsigned get_atomic() const { return m_atomic_spec;} + + int get_type() const + { + assert( !m_scalar_type.empty() ); + return m_scalar_type.front(); + } + + int get_type2() const + { + assert( m_scalar_type.size()==2 ); + return m_scalar_type.back(); + } + + void assign_bb(basic_block_t* basic_block) //assign instruction to a basic block + { + m_basic_block = basic_block; + } + basic_block_t* get_bb() { return m_basic_block;} + void set_m_instr_mem_index(unsigned index) { + m_instr_mem_index = index; + } + void set_PC( addr_t PC ) + { + m_PC = PC; + } + addr_t get_PC() const + { + return m_PC; + } + + unsigned get_m_instr_mem_index() { return m_instr_mem_index;} + unsigned get_cmpop() const { return m_compare_op;} + const symbol *get_label() const { return m_label;} + bool is_label() const { if(m_label){ assert(m_opcode==-1);return true;} return false;} + bool is_hi() const { return m_hi;} + bool is_lo() const { return m_lo;} + bool is_wide() const { return m_wide;} + bool is_uni() const { return m_uni;} + unsigned rounding_mode() const { return m_rounding_mode;} + unsigned saturation_mode() const { return m_saturation_mode;} + unsigned dimension() const { return m_geom_spec;} + enum vote_mode_t { vote_any, vote_all, vote_uni }; + enum vote_mode_t vote_mode() const { return m_vote_mode; } + + unsigned warp_size() const { return m_warp_size; } + int membar_level() const { return m_membar_level; } +private: + basic_block_t *m_basic_block; + unsigned m_uid; + addr_t m_PC; + std::string m_source_file; + unsigned m_source_line; + std::string m_source; + unsigned m_warp_size; + + const symbol *m_pred; + bool m_neg_pred; + int m_opcode; + const symbol *m_label; + std::vector<operand_info> m_operands; + operand_info m_return_var; + + std::list<int> m_options; + bool m_wide; + bool m_hi; + bool m_lo; + bool m_uni; //if branch instruction, this evaluates to true for uniform branches (ie jumps) + unsigned m_rounding_mode; + unsigned m_compare_op; + unsigned m_saturation_mode; + + std::list<int> m_scalar_type; + int m_space_spec; + int m_geom_spec; + int m_vector_spec; + int m_atomic_spec; + enum vote_mode_t m_vote_mode; + int m_membar_level; + int m_instr_mem_index; //index into m_instr_mem array +}; + +class param_info { +public: + param_info() { m_valid = false; m_value_set=false;} + param_info( unsigned index, std::string name, int type ) + { + m_valid = true; + m_value_set = false; + m_index = index; + m_name = name; + m_type = type; + } + void add_data( param_t v ) { + m_value_set = true; + m_value = v; + } + std::string get_name() const { return m_name; } + int get_type() const { return m_type; } + param_t get_value() const { assert(m_value_set); return m_value; } +private: + bool m_valid; + unsigned m_index; + std::string m_name; + int m_type; + bool m_value_set; + param_t m_value; +}; + +class function_info { +public: + function_info(int entry_point ) + { + m_entry_point = entry_point?true:false; + num_reconvergence_pairs = 0; + m_symtab = NULL; + m_assembled = false; + m_return_var_sym = NULL; + m_kernel_info.cmem = 0; + m_kernel_info.lmem = 0; + m_kernel_info.regs = 0; + m_kernel_info.smem = 0; + } + void set_name(const char *name) + { + m_name = name; + } + void set_symtab(symbol_table *symtab ) + { + m_symtab = symtab; + } + std::string get_name() + { + return m_name; + } + void print_insn( unsigned pc, FILE * fp ) const; + void add_inst( const std::list<ptx_instruction*> &instructions ) + { + m_instructions = instructions; + } + std::list<ptx_instruction*>::iterator find_next_real_instruction( std::list<ptx_instruction*>::iterator i ); + void create_basic_blocks( ); + + void print_basic_blocks(); + + void print_basic_block_links(); + void print_basic_block_dot(); + + void connect_basic_blocks( ); //iterate across m_basic_blocks of function, connecting basic blocks together + + //iterate across m_basic_blocks of function, + //finding postdominator blocks, using algorithm of + //Muchnick's Adv. Compiler Design & Implemmntation Fig 7.14 + void find_postdominators( ); + + //iterate across m_basic_blocks of function, + //finding immediate postdominator blocks, using algorithm of + //Muchnick's Adv. Compiler Design & Implemmntation Fig 7.15 + void find_ipostdominators( ); + + void print_postdominators(); + + void print_ipostdominators(); + + unsigned get_num_reconvergence_pairs(); + + void get_reconvergence_pairs(gpgpu_recon_t* recon_points); + + unsigned get_function_size() { return m_instructions.size();} + + void ptx_assemble(); + void ptx_decode_inst( ptx_thread_info *thd, + unsigned *op_type, + int *i1, + int *i2, + int *i3, + int *i4, + int *o1, + int *o2, + int *o3, + int *o4, + int *vectorin, + int *vectorout, + int *arch_reg ); + unsigned ptx_get_inst_op( ptx_thread_info *thread ); + void ptx_exec_inst( ptx_thread_info *thd, addr_t *addr, unsigned *space, unsigned *data_size, dram_callback_t* callback, unsigned warp_active_mask ); + void add_param( const char *name, struct param_t value ) + { + m_params[ name ] = value; + } + void add_param_name_and_type( unsigned index, std::string name, int type ); + void add_param_data( unsigned argn, struct gpgpu_ptx_sim_arg *args ); + void add_return_var( const symbol *rv ) + { + m_return_var_sym = rv; + } + void add_arg( const symbol *arg ) + { + assert( arg != NULL ); + m_args.push_back(arg); + } + void remove_args() + { + m_args.clear(); + } + unsigned num_args() const + { + return m_args.size(); + } + const symbol* get_arg( unsigned n ) const + { + assert( n < m_args.size() ); + return m_args[n]; + } + bool has_return() const + { + return m_return_var_sym != NULL; + } + const symbol *get_return_var() const + { + return m_return_var_sym; + } + const ptx_instruction *get_instruction( unsigned PC ) const + { + unsigned index = PC - m_start_PC; + if( index < m_instr_mem_size ) + return m_instr_mem[index]; + return NULL; + } + addr_t get_start_PC() const + { + return m_start_PC; + } + + void finalize( memory_space *param_mem, symbol_table *symtab ) + { + unsigned param_address = 0; + for( std::map<unsigned,param_info>::iterator i=m_ptx_param_info.begin(); i!=m_ptx_param_info.end(); i++ ) { + param_info &p = i->second; + std::string name = p.get_name(); + int type = p.get_type(); + param_t value = p.get_value(); + value.type = type; + symbol *param = symtab->lookup(name.c_str()); + unsigned xtype = param->type()->get_key().scalar_type(); + assert(xtype==(unsigned)type); + int tmp; + size_t size; + type_decode(xtype,size,tmp); + param_mem->write(param_address,size/8,&value); + param->set_address(param_address); + param_address += 8;//align to 64 bits so mem_access doesn't complain (before was size/8); + } + } + ptx_reg_t get_param( const std::string &name ) const + { + std::map<std::string,param_t>::const_iterator i = m_params.find(name); + if ( i == m_params.end() ) { + printf("Loader error: parameter \"%s\" value not defined in configuration\n", name.c_str() ); + abort(); + } else { + param_t x = i->second; + ptx_reg_t y; + switch ( x.type ) { + case S8_TYPE: + case S16_TYPE: + case S32_TYPE: + case S64_TYPE: + case B8_TYPE: + case B16_TYPE: + case B32_TYPE: + case B64_TYPE: + case U8_TYPE: + case U16_TYPE: + case U32_TYPE: + case U64_TYPE: + y.u64 = x.data.int_value; + break; + case F16_TYPE: + assert(0); + case F32_TYPE: + y.f32 = x.data.float_value; + break; + case F64_TYPE: + y.f64 = x.data.double_value; + break; + } + return y; + } + } + + const struct gpgpu_ptx_sim_kernel_info* get_kernel_info () { + return &m_kernel_info; + } + + const void set_kernel_info (const struct gpgpu_ptx_sim_kernel_info *info) { + m_kernel_info = *info; + } + symbol_table *get_symtab() + { + return m_symtab; + } + + static const ptx_instruction* pc_to_instruction(unsigned pc) + { + assert(pc > 0); + assert(pc <= s_g_pc_to_insn.size()); + return s_g_pc_to_insn[pc - 1]; + } + +private: + bool m_entry_point; + bool m_assembled; + std::string m_name; + ptx_instruction **m_instr_mem; + unsigned m_start_PC; + unsigned m_instr_mem_size; + std::map<std::string,param_t> m_params; + std::map<unsigned,param_info> m_ptx_param_info; + const symbol *m_return_var_sym; + std::vector<const symbol*> m_args; + std::list<ptx_instruction*> m_instructions; + std::vector<basic_block_t*> m_basic_blocks; + std::list<std::pair<unsigned, unsigned> > m_back_edges; + std::map<std::string,unsigned> labels; + unsigned num_reconvergence_pairs; + + //Registers/shmem/etc. used (from ptxas -v), loaded from ___.ptxinfo along with ___.ptx + struct gpgpu_ptx_sim_kernel_info m_kernel_info; + + symbol_table *m_symtab; + + static std::vector<ptx_instruction*> s_g_pc_to_insn; // a direct mapping from PC to instruction +}; + +/*******************************/ +// These declarations should be identical to those in ./../../cuda-sim-dev/libcuda/texture_types.h +enum cudaChannelFormatKind { + cudaChannelFormatKindSigned, + cudaChannelFormatKindUnsigned, + cudaChannelFormatKindFloat +}; + +struct cudaChannelFormatDesc { + int x; + int y; + int z; + int w; + enum cudaChannelFormatKind f; +}; + +struct cudaArray { + void *devPtr; + int devPtr32; + struct cudaChannelFormatDesc desc; + int width; + int height; + int size; //in bytes + unsigned dimensions; +}; + +enum cudaTextureAddressMode { + cudaAddressModeWrap, + cudaAddressModeClamp +}; + +enum cudaTextureFilterMode { + cudaFilterModePoint, + cudaFilterModeLinear +}; + +enum cudaTextureReadMode { + cudaReadModeElementType, + cudaReadModeNormalizedFloat +}; + +struct textureReference { + int normalized; + enum cudaTextureFilterMode filterMode; + enum cudaTextureAddressMode addressMode[2]; + struct cudaChannelFormatDesc channelDesc; +}; + +/**********************************/ + +struct textureInfo { + unsigned int texel_size; //size in bytes, e.g. (channelDesc.x+y+z+w)/8 + unsigned int Tx,Ty; //tiling factor dimensions of layout of texels per 64B cache block + unsigned int Tx_numbits,Ty_numbits; //log2(T) + unsigned int texel_size_numbits; //log2(texel_size) +}; + + +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_current_symbol_table; +extern symbol_table *g_entrypoint_symbol_table; +extern function_info *g_entrypoint_func_info; +extern symbol_table *g_global_symbol_table; +void init_parser(); + +extern "C" { +#endif + + void start_function( int entry_point ); + void add_function_name( const char *fname ); + void init_directive_state(); + void add_directive(); + void end_function(); + void add_identifier( const char *s, int array_dim, unsigned array_ident ); + void add_function_arg(); + void add_scalar_type_spec( int type_spec ); + void add_scalar_operand( const char *identifier ); + void add_neg_pred_operand( const char *identifier ); + void add_variables(); + void set_variable_type(); + void add_opcode( int opcode ); + void add_pred( const char *identifier, int negate ); + void add_2vector_operand( const char *d1, const char *d2 ); + void add_3vector_operand( const char *d1, const char *d2, const char *d3 ); + void add_4vector_operand( const char *d1, const char *d2, const char *d3, const char *d4 ); + void add_option(int option ); + void add_builtin_operand( int builtin, int dim_modifier ); + void add_memory_operand( ); + void add_literal_int( int value ); + void add_literal_float( float value ); + void add_literal_double( double value ); + void add_address_operand( const char *identifier, int offset ); + void add_label( const char *idenfiier ); + void add_vector_spec(int spec ); + void add_space_spec(int spec ); + void add_extern_spec(); + void add_instruction(); + void set_return(); + void add_alignment_spec( int spec ); + void add_array_initializer(); + void add_file( unsigned num, const char *filename ); + void *reset_symtab(); + void set_symtab(void*); + + +#define NON_ARRAY_IDENTIFIER 1 +#define ARRAY_IDENTIFIER_NO_DIM 2 +#define ARRAY_IDENTIFIER 3 + +#ifdef __cplusplus +} +#endif + +#endif |
