summaryrefslogtreecommitdiff
path: root/src/cuda-sim/cuda-sim.cc
diff options
context:
space:
mode:
authorTor Aamodt <[email protected]>2010-08-29 14:55:25 -0800
committerTor Aamodt <[email protected]>2010-08-29 14:55:25 -0800
commit80e1b49ff823190d0316623d414a343575c93eae (patch)
tree273e041128687af72e31161cce5759f6819aef97 /src/cuda-sim/cuda-sim.cc
parent5cb919d7fbe3e5b388b9c83b22762dad96da56b1 (diff)
- integrate changes from fermi-test (CL's under that path in range 7261-7418).
(add scoreboard logic from ptxplus branch and modified operand collector with parallel ALU/SFU pipelines) passing regressions [git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7419]
Diffstat (limited to 'src/cuda-sim/cuda-sim.cc')
-rw-r--r--src/cuda-sim/cuda-sim.cc170
1 files changed, 146 insertions, 24 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 )