From b3ce70a797756285ea9b15b3e5cf515d8b6a2b63 Mon Sep 17 00:00:00 2001 From: Tor Aamodt Date: Sun, 10 Oct 2010 21:19:52 -0800 Subject: 1. create function unit classes for SP, SFU, LD/ST. 2. refactor memory stage into a ld/st function unit 3. refactor memory access generation (moved into warp_inst_t class) the above should make supporting fermi uarch much easier passing CUDA 3.1 regression still need to... (a) update scoreboard to keep count of outstanding memory requests and use operand collector for writebacks into register file (b) add back shared memory pipeline delay (c) remove use of MSHR's for non-cached global/local accesses (d) replace texture cache with a split tag/data array pipe (e) re-implement memory_partition stuff so it makes more sense [git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7844] --- configs/QuadroFX5800/gpgpusim.config | 4 +- src/abstract_hardware_model.cc | 4 - src/abstract_hardware_model.h | 107 ++++- src/cuda-sim/cuda-sim.cc | 102 ++-- src/cuda-sim/ptx_ir.cc | 3 +- src/cuda-sim/ptx_ir.h | 11 +- src/cuda-sim/ptx_parser.cc | 10 +- src/gpgpu-sim/gpu-sim.cc | 52 +- src/gpgpu-sim/gpu-sim.h | 47 -- src/gpgpu-sim/mem_fetch.cc | 2 +- src/gpgpu-sim/shader.cc | 897 ++++++++++++++++++----------------- src/gpgpu-sim/shader.h | 345 +++++++++----- src/gpgpu-sim/stats.h | 3 + src/gpgpu-sim/visualizer.cc | 3 +- 14 files changed, 896 insertions(+), 694 deletions(-) diff --git a/configs/QuadroFX5800/gpgpusim.config b/configs/QuadroFX5800/gpgpusim.config index 2805674..e5e29bc 100644 --- a/configs/QuadroFX5800/gpgpusim.config +++ b/configs/QuadroFX5800/gpgpusim.config @@ -4,7 +4,6 @@ -gpgpu_ptx_force_max_capability 11 # high level architecture configuration --gpgpu_sm_uarch GT200 -gpgpu_n_shader 30 -gpgpu_n_mem 8 -gpgpu_clock_domains 325.0:650.0:650.0:800.0 @@ -56,8 +55,7 @@ -gpgpu_ptx_save_converted_ptxplus 1 # enable operand collector --gpgpu_operand_collector 1 --gpgpu_operand_collector_num_units 6 +-gpgpu_operand_collector_num_units_sp 6 -gpgpu_operand_collector_num_units_sfu 8 -visualizer_enabled 0 diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index b943a76..619b9b7 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -23,7 +23,3 @@ gpgpu_t::gpgpu_t() m_dev_malloc=GLOBAL_HEAP_START; } -void warp_inst_t::sort_accessq( unsigned qbegin ) -{ - std::stable_sort( m_accessq.begin()+qbegin,m_accessq.end()); -} diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 5ccdaf3..41fe025 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -386,7 +386,8 @@ public: is_vectorin=0; is_vectorout=0; space = memory_space_t(); - cycles = 0; + latency = 1; + initiation_interval = 1; for( unsigned i=0; i < MAX_REG_OPERANDS; i++ ) arch_reg[i]=-1; isize=0; @@ -411,7 +412,8 @@ public: int pred; // predicate register number int ar1, ar2; int arch_reg[MAX_REG_OPERANDS]; // register number for bank conflict evaluation - unsigned cycles; // 1/throughput for instruction + unsigned latency; // operation latency + unsigned initiation_interval; unsigned data_size; // what is the size of the word being operated on? memory_space_t space; @@ -423,16 +425,77 @@ protected: #define MAX_WARP_SIZE 32 +enum divergence_support_t { + POST_DOMINATOR = 1, + NUM_SIMD_MODEL +}; + +struct shader_core_config +{ + unsigned warp_size; + bool gpgpu_perfect_mem; + enum divergence_support_t model; + unsigned n_thread_per_shader; + unsigned max_warps_per_shader; + unsigned max_cta_per_core; //Limit on number of concurrent CTAs in shader core + unsigned pdom_sched_type; + bool gpgpu_no_dl1; + char *gpgpu_cache_texl1_opt; + char *gpgpu_cache_constl1_opt; + char *gpgpu_cache_dl1_opt; + char *gpgpu_cache_il1_opt; + unsigned n_mshr_per_shader; + bool gpgpu_dwf_reg_bankconflict; + int gpgpu_operand_collector_num_units_sp; + int gpgpu_operand_collector_num_units_sfu; + int gpgpu_operand_collector_num_units_mem; + bool gpgpu_stall_on_use; + bool gpgpu_cache_wt_through; + //Shader core resources + unsigned gpgpu_shmem_size; + unsigned gpgpu_shader_registers; + int gpgpu_warpdistro_shader; + int gpgpu_interwarp_mshr_merge; + int gpgpu_n_shmem_bank; + int gpgpu_n_cache_bank; + int gpgpu_shmem_port_per_bank; + int gpgpu_cache_port_per_bank; + int gpgpu_const_port_per_bank; + int gpgpu_shmem_pipe_speedup; + unsigned gpgpu_num_reg_banks; + unsigned gpu_max_cta_per_shader; // TODO: modify this for fermi... computed based upon kernel + // resource usage; used in shader_core_ctx::translate_local_memaddr + bool gpgpu_reg_bank_use_warp_id; + int gpgpu_coalesce_arch; + bool gpgpu_local_mem_map; + int gpu_padded_cta_size; + + unsigned max_sp_latency; + unsigned max_sfu_latency; + unsigned gpgpu_cache_texl1_linesize; + unsigned gpgpu_cache_constl1_linesize; + unsigned gpgpu_cache_dl1_linesize; + + static const address_type WORD_SIZE=4; + unsigned null_bank_func(address_type, unsigned) const { return 1; } + unsigned shmem_bank_func(address_type addr, unsigned) const; + unsigned dcache_bank_func(address_type add, unsigned line_size) const; +}; + +typedef unsigned (shader_core_config::*bank_func_t)(address_type add, unsigned line_size) const; +typedef address_type (*tag_func_t)(address_type add, unsigned line_size); + class warp_inst_t: public inst_t { public: // constructors - warp_inst_t( unsigned warp_size ) + warp_inst_t( const struct shader_core_config *config ) { - assert(warp_size<=MAX_WARP_SIZE); - m_warp_size=warp_size; + 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; } // modifiers @@ -452,18 +515,19 @@ public: } void issue( unsigned mask, unsigned warp_id, unsigned long long cycle ) { - for (int i=(int)m_warp_size-1; i>=0; i--) { + for (int i=(int)m_config->warp_size-1; i>=0; i--) { if( mask & (1<warp_size); m_per_scalar_thread_valid=true; } m_per_scalar_thread[n].memreqaddr = addr; @@ -474,7 +538,7 @@ public: class ptx_thread_info *thread ) { if( !m_per_scalar_thread_valid ) { - m_per_scalar_thread.resize(m_warp_size); + m_per_scalar_thread.resize(m_config->warp_size); m_per_scalar_thread_valid=true; m_isatomic=true; } @@ -487,11 +551,11 @@ public: warp_active_mask.reset(); for( std::vector::iterator i=active.begin(); i!=active.end(); ++i ) { unsigned t = *i; - assert( t < m_warp_size ); + assert( t < m_config->warp_size ); warp_active_mask.set(t); } if( m_isatomic ) { - for( unsigned i=0; i < m_warp_size; i++ ) { + for( unsigned i=0; i < m_config->warp_size; i++ ) { if( !warp_active_mask.test(i) ) { m_per_scalar_thread[i].callback.function = NULL; m_per_scalar_thread[i].callback.instruction = NULL; @@ -504,12 +568,13 @@ public: { warp_active_mask.reset(lane_id); } + void get_memory_access_list(); // accessors virtual void print_insn(FILE *fp) const { fprintf(fp," [inst @ pc=0x%04x] ", pc ); - for (int i=(int)m_warp_size-1; i>=0; i--) + for (int i=(int)m_config->warp_size-1; i>=0; i--) fprintf(fp, "%c", ((warp_active_mask[i])?'1':'0') ); } bool active( unsigned thread ) const { return warp_active_mask.test(thread); } @@ -533,22 +598,32 @@ public: bool isatomic() const { return m_isatomic; } - bool mem_accesses_computed() const { return m_mem_accesses_created; } - void set_mem_accesses_computed() { m_mem_accesses_created=true; } + unsigned warp_size() const { return m_config->warp_size; } + + bool mem_accesses_created() const { return m_mem_accesses_created; } + void set_mem_accesses_created() { m_mem_accesses_created=true; } bool accessq_empty() const { return m_accessq.empty(); } unsigned get_accessq_size() const { return m_accessq.size(); } mem_access_t &accessq( unsigned n ) { return m_accessq[n]; } mem_access_t &accessq_back() { return m_accessq.back(); } - void accessq_push_back( const mem_access_t &req ) { m_accessq.push_back(req); } void accessq_pop_back() { m_accessq.pop_back(); } - void sort_accessq( unsigned qbegin ); + + bool dispatch_delay() + { + if( cycles > 0 ) + cycles--; + return cycles > 0; + } + + void print( FILE *fout ) const; protected: bool m_empty; unsigned long long issue_cycle; + unsigned cycles; // used for implementing initiation interval delay bool m_isatomic; unsigned m_warp_id; - unsigned m_warp_size; + const struct shader_core_config *m_config; std::bitset warp_active_mask; struct per_thread_info { diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 89e89e8..e61659c 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -438,61 +438,64 @@ void ptx_print_insn( address_type pc, FILE *fp ) finfo->print_insn(pc,fp); } -static void get_opcode_info( const ptx_instruction *pI, unsigned opcode, unsigned *cycles, op_type *op ) +void ptx_instruction::get_opcode_info() { - *op = ALU_OP; - *cycles = 1; - if ( opcode == LD_OP ) { - *op = LOAD_OP; - } else if ( opcode == ST_OP ) { - *op = STORE_OP; - } else if ( opcode == BRA_OP ) { - *op = BRANCH_OP; - } else if ( opcode == BREAKADDR_OP ) { - *op = BRANCH_OP; - } else if ( opcode == TEX_OP ) { - *op = LOAD_OP; - } else if ( opcode == ATOM_OP ) { - *op = LOAD_OP; // timing model treats this like load for now - } else if ( opcode == BAR_OP ) { - *op = BARRIER_OP; - } else if ( opcode == MEMBAR_OP ) - *op = MEMORY_BARRIER_OP; - - // Floating point instructions - if( opcode == RCP_OP ) { - *cycles = 2; - *op = SFU_OP; - } else if ( opcode == LG2_OP || opcode == RSQRT_OP ) { - *cycles = 4; - *op = SFU_OP; - } else if( opcode == SQRT_OP || opcode == SIN_OP || opcode == COS_OP || opcode == EX2_OP ) { - *cycles = 4; - *op = SFU_OP; - } else if( opcode == DIV_OP ) { + op = ALU_OP; + initiation_interval = latency = 1; + switch( m_opcode ) { + case LD_OP: op = LOAD_OP; break; + case ST_OP: op = STORE_OP; break; + case BRA_OP: op = BRANCH_OP; break; + case BREAKADDR_OP: op = BRANCH_OP; break; + case TEX_OP: op = LOAD_OP; break; + case ATOM_OP: op = LOAD_OP; break; + case BAR_OP: op = BARRIER_OP; break; + case MEMBAR_OP: op = MEMORY_BARRIER_OP; break; + case RCP_OP: + latency = 2; + initiation_interval = 2; + op = SFU_OP; + break; + case LG2_OP: case RSQRT_OP: + latency = 4; + initiation_interval = 4; + op = SFU_OP; + break; + case SQRT_OP: case SIN_OP: case COS_OP: case EX2_OP: + latency = 10; + initiation_interval = 4; + op = SFU_OP; + break; + case DIV_OP: // Floating point only - if( pI->get_type() == F32_TYPE || pI->get_type() == F64_TYPE ) { - *cycles = 4; - *op = SFU_OP; + if( get_type() == F32_TYPE || get_type() == F64_TYPE ) { + latency = 10; + initiation_interval = 4; + op = SFU_OP; } - } - // Integer instructions - if( opcode == MUL_OP ) { - if( pI->get_type() == B32_TYPE || pI->get_type() == U32_TYPE || pI->get_type() == S32_TYPE ) { + break; + case MUL_OP: + if( get_type() == B32_TYPE || get_type() == U32_TYPE || get_type() == S32_TYPE ) { // 32-bit integer instruction - *cycles = 5; - *op = SFU_OP; + latency = 24; + initiation_interval = 5; + op = SFU_OP; } - if( pI->get_type() == F32_TYPE || pI->get_type() == F64_TYPE ) - *op = ALU_SFU_OP; - } - if( opcode == MAD_OP ) { - if( pI->get_type() == B32_TYPE || pI->get_type() == U32_TYPE || pI->get_type() == S32_TYPE ) { + if( get_type() == F32_TYPE || get_type() == F64_TYPE ) { + op = ALU_SFU_OP; + } + break; + case MAD_OP: + if( get_type() == B32_TYPE || get_type() == U32_TYPE || get_type() == S32_TYPE ) { // 32-bit integer instruction - *cycles = 6; - *op = SFU_OP; + latency = 30; + initiation_interval = 6; + op = SFU_OP; } - } + break; + default: + break; + } } void ptx_thread_info::ptx_fetch_inst( inst_t &inst ) const @@ -519,7 +522,6 @@ void ptx_instruction::pre_decode() ar2 = 0; bool has_dst = false ; - int opcode = get_opcode(); //determine the opcode switch ( get_opcode() ) { #define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: has_dst = (DST!=0); break; @@ -530,7 +532,7 @@ void ptx_instruction::pre_decode() break; } - get_opcode_info(this,opcode,&cycles,&op); + get_opcode_info(); // Get register operands int n=0,m=0; diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc index 8172f80..8d7fa11 100644 --- a/src/cuda-sim/ptx_ir.cc +++ b/src/cuda-sim/ptx_ir.cc @@ -983,7 +983,7 @@ ptx_instruction::ptx_instruction( int opcode, const char *file, unsigned line, const char *source, - unsigned warp_size ) : warp_inst_t(warp_size) + const shader_core_config *config ) : warp_inst_t(config) { m_uid = ++g_num_ptx_inst_uid; m_PC = 0; @@ -1011,7 +1011,6 @@ ptx_instruction::ptx_instruction( int opcode, m_geom_spec = 0; m_vector_spec = 0; m_atomic_spec = 0; - m_warp_size = warp_size; m_membar_level = 0; m_inst_size = 8; // bytes diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h index 07f2e36..84ded76 100644 --- a/src/cuda-sim/ptx_ir.h +++ b/src/cuda-sim/ptx_ir.h @@ -801,7 +801,7 @@ public: const char *file, unsigned line, const char *source, - unsigned warp_size ); + const shader_core_config *config ); void print_insn() const; virtual void print_insn( FILE *fp ) const; @@ -940,7 +940,6 @@ public: 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; } bool has_memory_read() const { @@ -966,6 +965,7 @@ public: } private: + void get_opcode_info(); basic_block_t *m_basic_block; unsigned m_uid; @@ -973,7 +973,6 @@ private: 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; @@ -1176,8 +1175,10 @@ public: static const ptx_instruction* pc_to_instruction(unsigned pc) { - assert(pc <= s_g_pc_to_insn.size()); - return s_g_pc_to_insn[pc]; + if( pc < s_g_pc_to_insn.size() ) + return s_g_pc_to_insn[pc]; + else + return NULL; } unsigned local_mem_framesize() const { diff --git a/src/cuda-sim/ptx_parser.cc b/src/cuda-sim/ptx_parser.cc index 5a65481..c4486a2 100644 --- a/src/cuda-sim/ptx_parser.cc +++ b/src/cuda-sim/ptx_parser.cc @@ -68,10 +68,10 @@ 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) +static const struct shader_core_config *g_shader_core_config; +void set_ptx_warp_size(const struct shader_core_config * warp_size) { - g_warp_size=warp_size; + g_shader_core_config=warp_size; } static bool g_debug_ir_generation=false; @@ -292,7 +292,7 @@ const ptx_instruction *ptx_instruction_lookup( const char *filename, unsigned li void add_instruction() { DPRINTF("add_instruction: %s", ((g_opcode>0)?g_opcode_string[g_opcode]:"