summaryrefslogtreecommitdiff
path: root/src/cuda-sim/ptx_ir.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuda-sim/ptx_ir.cc')
-rw-r--r--src/cuda-sim/ptx_ir.cc258
1 files changed, 257 insertions, 1 deletions
diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc
index b2c8552..d049a6a 100644
--- a/src/cuda-sim/ptx_ir.cc
+++ b/src/cuda-sim/ptx_ir.cc
@@ -78,7 +78,7 @@ extern "C" int ptx_error( const char *s );
// the program intermediate representation...
symbol_table *g_global_symbol_table = NULL;
-symbol_table *g_current_symbol_table = NULL;
+static symbol_table *g_current_symbol_table = NULL;
std::list<ptx_instruction*> g_instructions;
symbol *g_last_symbol = NULL;
std::map<std::string,symbol_table*> g_sym_name_to_symbol_table;
@@ -1424,3 +1424,259 @@ void copy_buffer_list_into_frame(ptx_thread_info * thread, arg_buffer_list_t &ar
}
}
+
+
+static std::list<operand_info> check_operands( int opcode,
+ const std::list<int> &scalar_type,
+ const std::list<operand_info> &operands )
+{
+ static int g_warn_literal_operands_two_type_inst;
+ if( (opcode == CVT_OP) || (opcode == SET_OP) || (opcode == SLCT_OP) || (opcode == TEX_OP) ) {
+ // just make sure these do not have have const operands...
+ if( !g_warn_literal_operands_two_type_inst ) {
+ std::list<operand_info>::const_iterator o;
+ for( o = operands.begin(); o != operands.end(); o++ ) {
+ const operand_info &op = *o;
+ if( op.is_literal() ) {
+ printf("GPGPU-Sim PTX: PTX uses two scalar type intruction with literal operand.\n");
+ g_warn_literal_operands_two_type_inst = 1;
+ }
+ }
+ }
+ } else {
+ assert( scalar_type.size() < 2 );
+ if( scalar_type.size() == 1 ) {
+ std::list<operand_info> result;
+ int inst_type = scalar_type.front();
+ std::list<operand_info>::const_iterator o;
+ for( o = operands.begin(); o != operands.end(); o++ ) {
+ const operand_info &op = *o;
+ if( op.is_literal() ) {
+ if( (op.get_type() == double_op_t) && (inst_type == F32_TYPE) ) {
+ ptx_reg_t v = op.get_literal_value();
+ float u = (float)v.f64;
+ operand_info n(u);
+ result.push_back(n);
+ } else {
+ result.push_back(op);
+ }
+ } else {
+ result.push_back(op);
+ }
+ }
+ return result;
+ }
+ }
+ return operands;
+}
+
+
+ptx_instruction::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,
+ memory_space_t space_spec,
+ const char *file,
+ unsigned line,
+ const char *source )
+{
+ m_uid = ++g_num_ptx_inst_uid;
+ m_PC = 0;
+ m_opcode = opcode;
+ m_pred = pred;
+ m_neg_pred = neg_pred;
+ m_label = label;
+ const std::list<operand_info> checked_operands = check_operands(opcode,scalar_type,operands);
+ m_operands.insert(m_operands.begin(), checked_operands.begin(), checked_operands.end() );
+ m_return_var = return_var;
+ m_options = options;
+ m_wide = false;
+ m_hi = false;
+ m_lo = false;
+ m_uni = false;
+ m_to_option = false;
+ m_cache_option = 0;
+ m_rounding_mode = RN_OPTION;
+ m_compare_op = -1;
+ m_saturation_mode = 0;
+ m_geom_spec = 0;
+ m_vector_spec = 0;
+ m_atomic_spec = 0;
+ m_warp_size = ::warp_size;
+ m_membar_level = 0;
+
+ std::list<int>::const_iterator i;
+ unsigned n=1;
+ for ( i=options.begin(); i!= options.end(); i++, n++ ) {
+ int last_ptx_inst_option = *i;
+ switch ( last_ptx_inst_option ) {
+ case EQU_OPTION:
+ case NEU_OPTION:
+ case LTU_OPTION:
+ case LEU_OPTION:
+ case GTU_OPTION:
+ case GEU_OPTION:
+ case EQ_OPTION:
+ case NE_OPTION:
+ case LT_OPTION:
+ case LE_OPTION:
+ case GT_OPTION:
+ case GE_OPTION:
+ case LS_OPTION:
+ case HS_OPTION:
+ m_compare_op = last_ptx_inst_option;
+ break;
+ case NUM_OPTION:
+ case NAN_OPTION:
+ m_compare_op = last_ptx_inst_option;
+ // assert(0); // finish this
+ break;
+ case SAT_OPTION:
+ m_saturation_mode = 1;
+ break;
+ case RNI_OPTION:
+ case RZI_OPTION:
+ case RMI_OPTION:
+ case RPI_OPTION:
+ case RN_OPTION:
+ case RZ_OPTION:
+ case RM_OPTION:
+ case RP_OPTION:
+ m_rounding_mode = last_ptx_inst_option;
+ break;
+ case HI_OPTION:
+ m_compare_op = last_ptx_inst_option;
+ m_hi = true;
+ assert( !m_lo );
+ assert( !m_wide );
+ break;
+ case LO_OPTION:
+ m_compare_op = last_ptx_inst_option;
+ m_lo = true;
+ assert( !m_hi );
+ assert( !m_wide );
+ break;
+ case WIDE_OPTION:
+ m_wide = true;
+ assert( !m_lo );
+ assert( !m_hi );
+ break;
+ case UNI_OPTION:
+ m_uni = true; // don't care... < now we DO care when constructing flowgraph>
+ break;
+ case GEOM_MODIFIER_1D:
+ case GEOM_MODIFIER_2D:
+ case GEOM_MODIFIER_3D:
+ m_geom_spec = last_ptx_inst_option;
+ break;
+ case V2_TYPE:
+ case V3_TYPE:
+ case V4_TYPE:
+ m_vector_spec = last_ptx_inst_option;
+ break;
+ case ATOMIC_AND:
+ case ATOMIC_OR:
+ case ATOMIC_XOR:
+ case ATOMIC_CAS:
+ case ATOMIC_EXCH:
+ case ATOMIC_ADD:
+ case ATOMIC_INC:
+ case ATOMIC_DEC:
+ case ATOMIC_MIN:
+ case ATOMIC_MAX:
+ m_atomic_spec = last_ptx_inst_option;
+ break;
+ case APPROX_OPTION:
+ break;
+ case FULL_OPTION:
+ break;
+ case ANY_OPTION:
+ m_vote_mode = vote_any;
+ break;
+ case ALL_OPTION:
+ m_vote_mode = vote_all;
+ break;
+ case GLOBAL_OPTION:
+ m_membar_level = GLOBAL_OPTION;
+ break;
+ case CTA_OPTION:
+ m_membar_level = CTA_OPTION;
+ break;
+ case FTZ_OPTION:
+ break;
+ case TO_OPTION:
+ m_to_option = true;
+ break;
+ case CA_OPTION: case CG_OPTION: case CS_OPTION: case LU_OPTION: case CV_OPTION:
+ m_cache_option = last_ptx_inst_option;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+ }
+ m_scalar_type = scalar_type;
+ m_space_spec = space_spec;
+ if( ( opcode == ST_OP || opcode == LD_OP ) && (space_spec == undefined_space) ) {
+ m_space_spec = generic_space;
+ }
+ m_source_file = file?file:"<unknown>";
+ m_source_line = line;
+ m_source = source;
+}
+
+void ptx_instruction::print_insn() const
+{
+ print_insn(stdout);
+ fflush(stdout);
+}
+
+void ptx_instruction::print_insn( FILE *fp ) const
+{
+ char buf[1024], *p;
+ snprintf(buf,1024,"%s", m_source.c_str());
+ p = strtok(buf,";");
+ if( !is_label() )
+ fprintf(fp,"PC=%3u [idx=%3u] ", m_PC, m_instr_mem_index );
+ else
+ fprintf(fp," " );
+ fprintf(fp,"(%s:%u) %s", m_source_file.c_str(), m_source_line, p );
+}
+
+unsigned function_info::sm_next_uid = 1;
+
+function_info::function_info(int entry_point )
+{
+ m_uid = sm_next_uid++;
+ m_entry_point = (entry_point==1)?true:false;
+ m_extern = (entry_point==2)?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;
+ m_local_mem_framesize = 0;
+}
+
+void function_info::print_insn( unsigned pc, FILE * fp ) const
+{
+ unsigned index = pc - m_start_PC;
+ fprintf(fp,"FUNC[%s]",m_name.c_str() );
+ if ( index >= m_instr_mem_size ) {
+ fprintf(fp, "<past last instruction (max pc=%u)>", m_start_PC + m_instr_mem_size - 1 );
+ } else {
+ if ( m_instr_mem[index] != NULL )
+ m_instr_mem[index]->print_insn(fp);
+ else
+ fprintf(fp, "<no instruction at pc = %u>", pc );
+ }
+}
+