diff options
Diffstat (limited to 'src/cuda-sim')
| -rw-r--r-- | src/cuda-sim/cuda-sim.cc | 170 | ||||
| -rw-r--r-- | src/cuda-sim/cuda-sim.h | 8 | ||||
| -rw-r--r-- | src/cuda-sim/instructions.cc | 6 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_ir.h | 27 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_sim.cc | 61 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_sim.h | 2 |
6 files changed, 220 insertions, 54 deletions
diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 9115774..2c317b2 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -524,13 +524,57 @@ 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, unsigned *op_type ) +{ + *op_type = ALU_OP; + *cycles = 1; + if ( opcode == LD_OP ) { + *op_type = LOAD_OP; + } else if ( opcode == ST_OP ) { + *op_type = STORE_OP; + } else if ( opcode == BRA_OP ) { + *op_type = BRANCH_OP; + } else if ( opcode == TEX_OP ) { + *op_type = LOAD_OP; + } else if ( opcode == ATOM_OP ) { + *op_type = LOAD_OP; // make atomics behave more like a load. + } else if ( opcode == BAR_OP ) { + *op_type = BARRIER_OP; + } + + // Floating point instructions + if( opcode == RCP_OP || opcode == LG2_OP || opcode == RSQRT_OP ) { + *cycles = 4; + *op_type = SFU_OP; + } else if( opcode == SQRT_OP || opcode == SIN_OP || opcode == COS_OP || opcode == EX2_OP ) { + *cycles = 4; + *op_type = SFU_OP; + } else if( opcode == DIV_OP ) { + // Floating point only + if( pI->get_type() == F32_TYPE || pI->get_type() == F64_TYPE ) { + *cycles = 8; + *op_type = SFU_OP; + } + } + // Integer instructions + if( opcode == MUL_OP ) { + if( pI->get_type() == B32_TYPE || pI->get_type() == U32_TYPE || pI->get_type() == S32_TYPE ) { + // 32-bit integer instruction + *cycles = 4; + *op_type = SFU_OP; + } + } +} + void function_info::ptx_decode_inst( ptx_thread_info *thread, 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 ) + int *arch_reg, + int *pred, + int *ar1, int *ar2 ) { addr_t pc = thread->get_pc(); unsigned index = pc - m_start_PC; @@ -549,21 +593,10 @@ void function_info::ptx_decode_inst( ptx_thread_info *thread, break; } - *op_type = ALU_OP; - if ( opcode == LD_OP ) { - *op_type = LOAD_OP; - } else if ( opcode == ST_OP ) { - *op_type = STORE_OP; - } else if ( opcode == BRA_OP ) { - *op_type = BRANCH_OP; - } else if ( opcode == TEX_OP ) { - *op_type = LOAD_OP; - } else if ( opcode == ATOM_OP ) { - *op_type = LOAD_OP; // make atomics behave more like a load. - } else if ( opcode == BAR_OP ) { - *op_type = BARRIER_OP; - } + unsigned cycles; + get_opcode_info(pI,opcode,&cycles,op_type); + // Get register operands int n=0,m=0; ptx_instruction::const_iterator op=pI->op_iter_begin(); for ( ; op != pI->op_iter_end(); op++, n++ ) { //process operands @@ -607,6 +640,37 @@ void function_info::ptx_decode_inst( ptx_thread_info *thread, } } } + + // Get predicate + if(pI->has_pred()) { + const operand_info &p = pI->get_pred(); + *pred = p.reg_num(); + } + + // Get address registers inside memory operands. + // Assuming only one memory operand per instruction, + // and maximum of two address registers for one memory operand. + if( pI->has_memory_read() || pI->has_memory_write() ) { + ptx_instruction::const_iterator op=pI->op_iter_begin(); + for ( ; op != pI->op_iter_end(); op++, n++ ) { //process operands + const operand_info &o = *op; + + // memory operand with addressing (ex. s[0x4] or g[$r1]) + if(o.is_memory_operand2()) { + // memory operand with one address register (ex. g[$r1] or s[$r2+0x4]) + if(o.get_double_operand_type() == 0 && o.is_memory_operand()){ + const symbol *base_addr = o.get_symbol(); + if( base_addr->is_reg() ) + *ar1 = base_addr->reg_num(); + } + // memory operand with two address register (ex. s[$r1+$r1] or g[$r1+=$r2]) + else if(o.get_double_operand_type() == 1 || o.get_double_operand_type() == 2) { + *ar1 = o.reg1_num(); + *ar2 = o.reg2_num(); + } + } + } + } } void function_info::add_param_name_type_size( unsigned index, std::string name, int type, size_t size ) @@ -773,11 +837,13 @@ unsigned datatype2size( unsigned data_type ) } unsigned g_warp_active_mask; +FILE *ptx_inst_debug_file; void function_info::ptx_exec_inst( ptx_thread_info *thread, addr_t *addr, memory_space_t *space, - unsigned *data_size, + unsigned *data_size, + unsigned *cycles, dram_callback_t* callback, unsigned warp_active_mask ) { @@ -832,10 +898,9 @@ void function_info::ptx_exec_inst( ptx_thread_info *thread, addr_t insn_memaddr = 0xFEEBDAED; memory_space_t insn_space = undefined_space; unsigned insn_data_size = 0; - if ( pI->get_opcode() == LD_OP || pI->get_opcode() == ST_OP || pI->get_opcode() == TEX_OP ) { + if ( (pI->has_memory_read() || pI->has_memory_write()) ) { insn_memaddr = thread->last_eaddr(); insn_space = thread->last_space(); - unsigned to_type = pI->get_type(); insn_data_size = datatype2size(to_type); } @@ -855,6 +920,47 @@ void function_info::ptx_exec_inst( ptx_thread_info *thread, callback->instruction = NULL; } + // Set number of cycles for this instruction + int opcode = pI->get_opcode(); //determine the opcode + unsigned op_type; + get_opcode_info(pI,opcode,cycles,&op_type); + + if (pI->get_opcode() == TEX_OP) { + *addr = thread->last_eaddr(); + *space = thread->last_space(); + + unsigned to_type = pI->get_type(); + switch ( to_type ) { + case B8_TYPE: + case S8_TYPE: + case U8_TYPE: + *data_size = 1; break; + case B16_TYPE: + case S16_TYPE: + case U16_TYPE: + case F16_TYPE: + *data_size = 2; break; + case B32_TYPE: + case S32_TYPE: + case U32_TYPE: + case F32_TYPE: + *data_size = 4; break; + case B64_TYPE: + case S64_TYPE: + case U64_TYPE: + case F64_TYPE: + *data_size = 8; break; + default: assert(0); break; + } + } + + // Output register information to file and stdout + if( g_ptx_inst_debug_to_file != 0 && + (g_ptx_inst_debug_thread_uid == 0 || g_ptx_inst_debug_thread_uid == thread->get_uid()) ) { + thread->dump_modifiedregs(ptx_inst_debug_file); + thread->dump_regs(ptx_inst_debug_file); + } + if ( g_debug_execution >= 6 ) { if ( ptx_debug_exec_dump_cond<6>(thread->get_uid(), pc) ) thread->dump_modifiedregs(); @@ -1414,6 +1520,8 @@ void gpgpu_cuda_ptx_sim_main_func( const char *kernel_key, dim3 gridDim, dim3 bl time_t end_time, elapsed_time, days, hrs, minutes, sec; int i1, i2, i3, i4, o1, o2, o3, o4; int vectorin, vectorout; + int pred; + int ar1, ar2; gpgpu_cuda_ptx_sim_init_grid(kernel_key, args,gridDim,blockDim); @@ -1498,6 +1606,7 @@ void gpgpu_cuda_ptx_sim_main_func( const char *kernel_key, dim3 gridDim, dim3 bl unsigned op_type; addr_t addr; + unsigned cycles; memory_space_t space; int arch_reg[MAX_REG_OPERANDS] = { -1 }; unsigned data_size; @@ -1505,8 +1614,8 @@ void gpgpu_cuda_ptx_sim_main_func( const char *kernel_key, dim3 gridDim, dim3 bl unsigned warp_active_mask = (unsigned)-1; // vote instruction with diverged warps won't execute correctly // in functional simulation mode - g_func_info->ptx_decode_inst( thread, &op_type, &i1, &i2, &i3, &i4, &o1, &o2, &o3, &o4, &vectorin, &vectorout, arch_reg ); - g_func_info->ptx_exec_inst( thread, &addr, &space, &data_size, &callback, warp_active_mask ); + g_func_info->ptx_decode_inst( thread, &op_type, &i1, &i2, &i3, &i4, &o1, &o2, &o3, &o4, &vectorin, &vectorout, arch_reg, &pred, &ar1, &ar2 ); + g_func_info->ptx_exec_inst( thread, &addr, &space, &data_size, &cycles, &callback, warp_active_mask ); } } } @@ -1532,7 +1641,7 @@ void gpgpu_cuda_ptx_sim_main_func( const char *kernel_key, dim3 gridDim, dim3 bl fflush(stdout); } -void ptx_decode_inst( void *thd, unsigned *op, int *i1, int *i2, int *i3, int *i4, int *o1, int *o2, int *o3, int *o4, int *vectorin, int *vectorout, int *arch_reg ) +void ptx_decode_inst( void *thd, unsigned *op, int *i1, int *i2, int *i3, int *i4, int *o1, int *o2, int *o3, int *o4, int *vectorin, int *vectorout, int *arch_reg, int *pred, int *ar1, int *ar2 ) { *op = NO_OP; *o1 = 0; @@ -1546,22 +1655,35 @@ void ptx_decode_inst( void *thd, unsigned *op, int *i1, int *i2, int *i3, int *i *vectorin = 0; *vectorout = 0; std::fill_n(arch_reg, MAX_REG_OPERANDS, -1); + *pred = 0; + *ar1 = 0; + *ar2 = 0; if ( thd == NULL ) return; ptx_thread_info *thread = (ptx_thread_info *) thd; g_func_info = thread->func_info(); - g_func_info->ptx_decode_inst(thread,op,i1,i2,i3,i4,o1,o2,o3,o4,vectorin,vectorout,arch_reg); + g_func_info->ptx_decode_inst(thread,op,i1,i2,i3,i4,o1,o2,o3,o4,vectorin,vectorout,arch_reg,pred,ar1,ar2); +} + +extern "C" unsigned ptx_get_inst_op( void *thd) +{ + if ( thd == NULL ) + return NO_OP; + + ptx_thread_info *thread = (ptx_thread_info *) thd; + return(thread->func_info())->ptx_get_inst_op(thread); } -void ptx_exec_inst( void *thd, address_type *addr, memory_space_t *space, unsigned *data_size, dram_callback_t* callback, unsigned warp_active_mask ) +void ptx_exec_inst( void *thd, address_type *addr, memory_space_t *space, unsigned *data_size, unsigned *cycles, dram_callback_t* callback, unsigned warp_active_mask ) { if ( thd == NULL ) return; + *cycles = 1; ptx_thread_info *thread = (ptx_thread_info *) thd; g_func_info = thread->func_info(); - g_func_info->ptx_exec_inst( thread, addr, space, data_size, callback, warp_active_mask ); + g_func_info->ptx_exec_inst( thread, addr, space, data_size, cycles, callback, warp_active_mask ); } void ptx_dump_regs( void *thd ) diff --git a/src/cuda-sim/cuda-sim.h b/src/cuda-sim/cuda-sim.h index baf3b63..6f931fc 100644 --- a/src/cuda-sim/cuda-sim.h +++ b/src/cuda-sim/cuda-sim.h @@ -89,11 +89,15 @@ void ptx_decode_inst( void *thd, int *o4, int *vectorin, int *vectorout, - int *arch_reg ); + int *arch_reg, + int *pred, + int *ar1, + int *ar2 ); void ptx_exec_inst( void *thd, address_type *addr, memory_space_t *space, - unsigned *data_size, + unsigned *data_size, + unsigned *cycles, dram_callback_t* callback, unsigned warp_active_mask ); diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 47b3ebb..cbf4c44 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -2639,7 +2639,7 @@ void st_impl( const ptx_instruction *pI, ptx_thread_info *thread ) thread->get_vector_operand_values(src1, ptx_regs, 2); mem->write(addr,size/8,&ptx_regs[0].s64,thread,pI); mem->write(addr+size/8,size/8,&ptx_regs[1].s64,thread,pI); - free(ptx_regs); + delete [] ptx_regs; } if (vector_spec == V3_TYPE) { ptx_reg_t* ptx_regs = new ptx_reg_t[3]; @@ -2647,7 +2647,7 @@ void st_impl( const ptx_instruction *pI, ptx_thread_info *thread ) mem->write(addr,size/8,&ptx_regs[0].s64,thread,pI); mem->write(addr+size/8,size/8,&ptx_regs[1].s64,thread,pI); mem->write(addr+2*size/8,size/8,&ptx_regs[2].s64,thread,pI); - free(ptx_regs); + delete [] ptx_regs; } if (vector_spec == V4_TYPE) { ptx_reg_t* ptx_regs = new ptx_reg_t[4]; @@ -2656,7 +2656,7 @@ void st_impl( const ptx_instruction *pI, ptx_thread_info *thread ) mem->write(addr+size/8,size/8,&ptx_regs[1].s64,thread,pI); mem->write(addr+2*size/8,size/8,&ptx_regs[2].s64,thread,pI); mem->write(addr+3*size/8,size/8,&ptx_regs[3].s64,thread,pI); - free(ptx_regs); + delete [] ptx_regs; } } thread->m_last_effective_address = addr; diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h index 3a2a4e3..0887df0 100644 --- a/src/cuda-sim/ptx_ir.h +++ b/src/cuda-sim/ptx_ir.h @@ -565,6 +565,13 @@ public: 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;} + // Memory operand with immediate access (ex. s[0x0004] or g[$r1+=0x0004]) + bool is_memory_operand2() const { + /* TODO: modify after integrate with ptxplus*/ + return m_type == memory_t; + /*return (m_addr_space==1 || m_addr_space==2 || m_addr_space==3 || m_addr_space==4);*/ + } + bool is_literal() const { return m_type == int_t || m_type == float_op_t || m_type == double_op_t || @@ -621,6 +628,8 @@ public: bool is_neg_pred() const { return m_neg_pred; } bool is_valid() const { return m_valid; } + int get_double_operand_type() const { return 0; /* TODO: modify after integrate with ptxplus*/ } + private: unsigned m_uid; bool m_valid; @@ -828,6 +837,17 @@ public: unsigned warp_size() const { return m_warp_size; } int membar_level() const { return m_membar_level; } + + bool has_memory_read() const { + if( m_opcode == LD_OP || m_opcode == TEX_OP ) + return true; + return false; + } + bool has_memory_write() const { + if( m_opcode == ST_OP ) return true; + return false; + } + private: basic_block_t *m_basic_block; unsigned m_uid; @@ -958,8 +978,11 @@ public: int *o4, int *vectorin, int *vectorout, - int *arch_reg ); - void ptx_exec_inst( ptx_thread_info *thd, addr_t *addr, memory_space_t *space, unsigned *data_size, dram_callback_t* callback, unsigned warp_active_mask ); + int *arch_reg, + int *pred, + int *ar1, int *ar2 ); + void ptx_exec_inst( ptx_thread_info *thd, addr_t *addr, memory_space_t *space, unsigned *data_size, unsigned *cycles, dram_callback_t* callback, unsigned warp_active_mask ); + unsigned ptx_get_inst_op( ptx_thread_info *thread ); void add_param( const char *name, struct param_t value ) { m_kernel_params[ name ] = value; diff --git a/src/cuda-sim/ptx_sim.cc b/src/cuda-sim/ptx_sim.cc index b433fb3..685aedb 100644 --- a/src/cuda-sim/ptx_sim.cc +++ b/src/cuda-sim/ptx_sim.cc @@ -310,44 +310,49 @@ void ptx_thread_info::print_insn( unsigned pc, FILE * fp ) const m_func_info->print_insn(pc,fp); } -static void print_reg( std::string name, ptx_reg_t value, symbol_table *symtab ) +static void print_reg( FILE *fp, std::string name, ptx_reg_t value, symbol_table *symtab ) { const symbol *sym = symtab->lookup(name.c_str()); - printf(" %8s ", name.c_str() ); + fprintf(fp," %8s ", name.c_str() ); if( sym == NULL ) { - printf("<unknown type> 0x%llx\n", (unsigned long long ) value.u64 ); + fprintf(fp,"<unknown type> 0x%llx\n", (unsigned long long ) value.u64 ); return; } const type_info *t = sym->type(); if( t == NULL ) { - printf("<unknown type> 0x%llx\n", (unsigned long long ) value.u64 ); + fprintf(fp,"<unknown type> 0x%llx\n", (unsigned long long ) value.u64 ); return; } type_info_key ti = t->get_key(); switch ( ti.scalar_type() ) { - case S8_TYPE: printf(".s8 %d\n", value.s8 ); break; - case S16_TYPE: printf(".s16 %d\n", value.s16 ); break; - case S32_TYPE: printf(".s32 %d\n", value.s32 ); break; - case S64_TYPE: printf(".s64 %Ld\n", value.s64 ); break; - case U8_TYPE: printf(".u8 0x%02x\n", (unsigned) value.u8 ); break; - case U16_TYPE: printf(".u16 0x%04x\n", (unsigned) value.u16 ); break; - case U32_TYPE: printf(".u32 0x%08x\n", (unsigned) value.u32 ); break; - case U64_TYPE: printf(".u64 0x%llx\n", value.u64 ); break; - case F16_TYPE: printf(".f16 %f [0x%04x]\n", value.f16, (unsigned) value.u16 ); break; - case F32_TYPE: printf(".f32 %.15lf [0x%08x]\n", value.f32, value.u32 ); break; - case F64_TYPE: printf(".f64 %.15le [0x%016llx]\n", value.f64, value.u64 ); break; - case B8_TYPE: printf(".b8 0x%02x\n", (unsigned) value.u8 ); break; - case B16_TYPE: printf(".b16 0x%04x\n", (unsigned) value.u16 ); break; - case B32_TYPE: printf(".b32 0x%08x\n", (unsigned) value.u32 ); break; - case B64_TYPE: printf(".b64 0x%llx\n", (unsigned long long ) value.u64 ); break; - case PRED_TYPE: printf(".pred %u\n", (unsigned) value.pred ); break; + case S8_TYPE: fprintf(fp,".s8 %d\n", value.s8 ); break; + case S16_TYPE: fprintf(fp,".s16 %d\n", value.s16 ); break; + case S32_TYPE: fprintf(fp,".s32 %d\n", value.s32 ); break; + case S64_TYPE: fprintf(fp,".s64 %Ld\n", value.s64 ); break; + case U8_TYPE: fprintf(fp,".u8 0x%02x\n", (unsigned) value.u8 ); break; + case U16_TYPE: fprintf(fp,".u16 0x%04x\n", (unsigned) value.u16 ); break; + case U32_TYPE: fprintf(fp,".u32 0x%08x\n", (unsigned) value.u32 ); break; + case U64_TYPE: fprintf(fp,".u64 0x%llx\n", value.u64 ); break; + case F16_TYPE: fprintf(fp,".f16 %f [0x%04x]\n", value.f16, (unsigned) value.u16 ); break; + case F32_TYPE: fprintf(fp,".f32 %.15lf [0x%08x]\n", value.f32, value.u32 ); break; + case F64_TYPE: fprintf(fp,".f64 %.15le [0x%016llx]\n", value.f64, value.u64 ); break; + case B8_TYPE: fprintf(fp,".b8 0x%02x\n", (unsigned) value.u8 ); break; + case B16_TYPE: fprintf(fp,".b16 0x%04x\n", (unsigned) value.u16 ); break; + case B32_TYPE: fprintf(fp,".b32 0x%08x\n", (unsigned) value.u32 ); break; + case B64_TYPE: fprintf(fp,".b64 0x%llx\n", (unsigned long long ) value.u64 ); break; + case PRED_TYPE: fprintf(fp,".pred %u\n", (unsigned) value.pred ); break; default: - printf( "non-scalar type\n" ); + fprintf( fp, "non-scalar type\n" ); break; } } +static void print_reg( std::string name, ptx_reg_t value, symbol_table *symtab ) +{ + print_reg(stdout,name,value,symtab); +} + void ptx_thread_info::callstack_push( unsigned pc, unsigned rpc, const symbol *return_var_src, const symbol *return_var_dst, unsigned call_uid ) { m_RPC = -1; @@ -438,7 +443,12 @@ const ptx_instruction *ptx_thread_info::get_inst( addr_t pc ) const void ptx_thread_info::dump_regs() { - printf("Register File Contents:\n"); + dump_regs(stdout); +} + +void ptx_thread_info::dump_regs( FILE *fp ) +{ + fprintf(fp,"Register File Contents:\n"); reg_map_t::const_iterator r; for ( r=m_regs.back().begin(); r != m_regs.back().end(); ++r ) { std::string name = r->first->name(); @@ -449,9 +459,14 @@ void ptx_thread_info::dump_regs() void ptx_thread_info::dump_modifiedregs() { + dump_modifiedregs(stdout); +} + +void ptx_thread_info::dump_modifiedregs(FILE *fp) +{ if( m_debug_trace_regs_modified.empty() ) return; - printf("Modified Registers:\n"); + fprintf(fp,"Modified Registers:\n"); reg_map_t::const_iterator r; for ( r=m_debug_trace_regs_modified.begin(); r != m_debug_trace_regs_modified.end(); ++r ) { std::string name = r->first->name(); diff --git a/src/cuda-sim/ptx_sim.h b/src/cuda-sim/ptx_sim.h index d712275..8730f2b 100644 --- a/src/cuda-sim/ptx_sim.h +++ b/src/cuda-sim/ptx_sim.h @@ -414,7 +414,9 @@ public: m_PC = m_NPC; } void dump_regs(); + void dump_regs(FILE *fp); void dump_modifiedregs(); + void dump_modifiedregs(FILE *fp); void clear_modifiedregs() { m_debug_trace_regs_modified.clear();} function_info *get_finfo() { return m_func_info; } const function_info *get_finfo() const { return m_func_info; } |
