diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/abstract_hardware_model.h | 1 | ||||
| -rw-r--r-- | src/cuda-sim/cuda-sim.cc | 2 | ||||
| -rw-r--r-- | src/cuda-sim/instructions.cc | 138 | ||||
| -rw-r--r-- | src/cuda-sim/opcodes.def | 1 | ||||
| -rw-r--r-- | src/cuda-sim/ptx.l | 1 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_ir.cc | 3 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_ir.h | 3 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_parser.cc | 5 |
8 files changed, 144 insertions, 10 deletions
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 46534ab..c6e3b43 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -1132,6 +1132,7 @@ class warp_inst_t : public inst_t { void print(FILE *fout) const; unsigned get_uid() const { return m_uid; } unsigned get_schd_id() const { return m_scheduler_id; } + active_mask_t get_warp_active_mask() const { return m_warp_active_mask; } protected: unsigned m_uid; diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 75dd3c8..71f0703 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -1741,7 +1741,7 @@ void ptx_thread_info::ptx_exec_inst(warp_inst_t &inst, unsigned lane_id) { } else { const ptx_instruction *pI_saved = pI; ptx_instruction *pJ = NULL; - if (pI->get_opcode() == VOTE_OP) { + if (pI->get_opcode() == VOTE_OP || pI->get_opcode() == ACTIVEMASK_OP) { pJ = new ptx_instruction(*pI); *((warp_inst_t *)pJ) = inst; // copy active mask information pI = pJ; diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index bf9a040..1090ba4 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -166,6 +166,8 @@ void inst_not_implemented(const ptx_instruction *pI); ptx_reg_t srcOperandModifiers(ptx_reg_t opData, operand_info opInfo, operand_info dstInfo, unsigned type, ptx_thread_info *thread); + +void video_mem_instruction(const ptx_instruction *pI, ptx_thread_info *thread, int op_code); void sign_extend(ptx_reg_t &data, unsigned src_size, const operand_info &dst); @@ -1709,8 +1711,40 @@ void bfi_impl(const ptx_instruction *pI, ptx_thread_info *thread) { } thread->set_operand_value(dst, data, i_type, thread, pI); } -void bfind_impl(const ptx_instruction *pI, ptx_thread_info *thread) { - inst_not_implemented(pI); +void bfind_impl(const ptx_instruction *pI, ptx_thread_info *thread) +{ + const operand_info &dst = pI->dst(); + const operand_info &src1 = pI->src1(); + const unsigned i_type = pI->get_type(); + + const ptx_reg_t src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + const int msb = ( i_type == U32_TYPE || i_type == S32_TYPE) ? 31 : 63; + + unsigned long a = 0; + switch (i_type) + { + case S32_TYPE: a = src1_data.s32; break; + case U32_TYPE: a = src1_data.u32; break; + case S64_TYPE: a = src1_data.s64; break; + case U64_TYPE: a = src1_data.u64; break; + default: assert(false); abort(); + } + + // negate negative signed inputs + if ( ( i_type == S32_TYPE || i_type == S64_TYPE ) && ( a & ( 1 << msb ) ) ) { + a = ~a; + } + uint32_t d_data = 0xffffffff; + for (uint32_t i = msb; i >= 0; i--) { + if (a & (1<<i)) { d_data = i; break; } + } + + // if (.shiftamt && d != 0xffffffff) { d = msb - d; } + + // store d + thread->set_operand_value(dst, d_data, U32_TYPE, thread, pI); + + } void bra_impl(const ptx_instruction *pI, ptx_thread_info *thread) { @@ -6301,11 +6335,17 @@ void vadd_impl(const ptx_instruction *pI, ptx_thread_info *thread) { void vmad_impl(const ptx_instruction *pI, ptx_thread_info *thread) { inst_not_implemented(pI); } -void vmax_impl(const ptx_instruction *pI, ptx_thread_info *thread) { - inst_not_implemented(pI); + +#define VMAX 0 +#define VMIN 1 + +void vmax_impl(const ptx_instruction *pI, ptx_thread_info *thread) +{ + video_mem_instruction(pI, thread, VMAX); } -void vmin_impl(const ptx_instruction *pI, ptx_thread_info *thread) { - inst_not_implemented(pI); +void vmin_impl(const ptx_instruction *pI, ptx_thread_info *thread) +{ + video_mem_instruction(pI, thread, VMIN); } void vset_impl(const ptx_instruction *pI, ptx_thread_info *thread) { inst_not_implemented(pI); @@ -6400,6 +6440,15 @@ void vote_impl(const ptx_instruction *pI, ptx_thread_info *thread) { } } +void activemask_impl( const ptx_instruction *pI, ptx_thread_info *thread ) +{ + active_mask_t l_activemask_bitset = pI->get_warp_active_mask(); + uint32_t l_activemask_uint = static_cast<uint32_t>(l_activemask_bitset.to_ulong()); + + const operand_info &dst = pI->dst(); + thread->set_operand_value(dst, l_activemask_uint, U32_TYPE, thread, pI); +} + void xor_impl(const ptx_instruction *pI, ptx_thread_info *thread) { ptx_reg_t src1_data, src2_data, data; @@ -6477,3 +6526,80 @@ ptx_reg_t srcOperandModifiers(ptx_reg_t opData, operand_info opInfo, return result; } + +void video_mem_instruction(const ptx_instruction *pI, ptx_thread_info *thread, int op_code) +{ + const operand_info &dst = pI->dst(); // d + const operand_info &src1 = pI->src1(); // a + const operand_info &src2 = pI->src2(); // b + const operand_info &src3 = pI->src3(); // c + + const unsigned i_type = pI->get_type(); + + std::list<int> scalar_type; + std::list<int> options; + + ptx_reg_t a, b, ta, tb, c, data; + + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + b = thread->get_operand_value(src2, dst, i_type, thread, 1); + c = thread->get_operand_value(src3, dst, i_type, thread, 1); + + // TODO: implement this + // ta = partSelectSignExtend( a, atype ); + // tb = partSelectSignExtend( b, btype ); + ta = a; + tb = b; + + options = pI->get_options(); + assert(options.size() == 1); + + auto option = options.begin(); + assert(*option == ATOMIC_MAX || *option == ATOMIC_MIN); + + switch ( i_type ) { + case S32_TYPE: { + // assert all operands are S32_TYPE: + scalar_type = pI->get_scalar_type(); + for (auto scalar : scalar_type) + { + assert(scalar == S32_TYPE); + } + assert(scalar_type.size() == 3); + scalar_type.clear(); + + switch (op_code) + { + case VMAX: + data.s32 = MY_MAX_I(ta.s32, tb.s32); + break; + case VMIN: + data.s32 = MY_MIN_I(ta.s32, tb.s32); + break; + default: + assert(0); + } + + switch (*option) + { + case ATOMIC_MAX: + data.s32 = MY_MAX_I(data.s32, c.s32); + break; + case ATOMIC_MIN: + data.s32 = MY_MIN_I(data.s32, c.s32); + break; + default: + assert(0); // not yet implemented + } + break; + + } + default: + assert(0); // not yet implemented + } + + thread->set_operand_value(dst, data, i_type, thread, pI); + + return; +} + diff --git a/src/cuda-sim/opcodes.def b/src/cuda-sim/opcodes.def index c4d6a83..f5bf156 100644 --- a/src/cuda-sim/opcodes.def +++ b/src/cuda-sim/opcodes.def @@ -129,6 +129,7 @@ OP_DEF(VSHL_OP,vshl_impl,"vshl",0,11) OP_DEF(VSHR_OP,vshr_impl,"vshr",0,11) OP_DEF(VSUB_OP,vsub_impl,"vsub",0,11) OP_DEF(VOTE_OP,vote_impl,"vote",0,3) +OP_DEF(ACTIVEMASK_OP,activemask_impl,"activemask",1,3) OP_DEF(XOR_OP,xor_impl,"xor",1,1) OP_DEF(NOP_OP,nop_impl,"nop",0,7) OP_DEF(BREAK_OP,break_impl,"break",0,3) diff --git a/src/cuda-sim/ptx.l b/src/cuda-sim/ptx.l index 2dadda4..6754045 100644 --- a/src/cuda-sim/ptx.l +++ b/src/cuda-sim/ptx.l @@ -158,6 +158,7 @@ vshl TC; yylval->int_value = VSHL_OP; return OPCODE; vshr TC; yylval->int_value = VSHR_OP; return OPCODE; vsub TC; yylval->int_value = VSUB_OP; return OPCODE; vote TC; yylval->int_value = VOTE_OP; return OPCODE; +activemask TC; yylval->int_value = ACTIVEMASK_OP; return OPCODE; xor TC; yylval->int_value = XOR_OP; return OPCODE; nop TC; yylval->int_value = NOP_OP; return OPCODE; break TC; yylval->int_value = BREAK_OP; return OPCODE; diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc index aa1c25a..e5b5fb7 100644 --- a/src/cuda-sim/ptx_ir.cc +++ b/src/cuda-sim/ptx_ir.cc @@ -1147,7 +1147,8 @@ static std::list<operand_info> check_operands( const std::list<operand_info> &operands, gpgpu_context *ctx) { static int g_warn_literal_operands_two_type_inst; if ((opcode == CVT_OP) || (opcode == SET_OP) || (opcode == SLCT_OP) || - (opcode == TEX_OP) || (opcode == MMA_OP) || (opcode == DP4A_OP)) { + (opcode == TEX_OP) || (opcode == MMA_OP) || (opcode == DP4A_OP) || + (opcode == VMIN_OP) || (opcode == VMAX_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; diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h index 6627847..8c4ad4d 100644 --- a/src/cuda-sim/ptx_ir.h +++ b/src/cuda-sim/ptx_ir.h @@ -966,6 +966,9 @@ class ptx_instruction : public warp_inst_t { int get_pred_mod() const { return m_pred_mod; } const char *get_source() const { return m_source.c_str(); } + const std::list<int> get_scalar_type() const {return m_scalar_type;} + const std::list<int> get_options() const {return m_options;} + typedef std::vector<operand_info>::const_iterator const_iterator; const_iterator op_iter_begin() const { return m_operands.begin(); } diff --git a/src/cuda-sim/ptx_parser.cc b/src/cuda-sim/ptx_parser.cc index 3ae8de3..549c08c 100644 --- a/src/cuda-sim/ptx_parser.cc +++ b/src/cuda-sim/ptx_parser.cc @@ -624,8 +624,9 @@ void ptx_recognizer::add_scalar_type_spec(int type_spec) { parse_assert((g_opcode == -1) || (g_opcode == CVT_OP) || (g_opcode == SET_OP) || (g_opcode == SLCT_OP) || (g_opcode == TEX_OP) || (g_opcode == MMA_OP) || - (g_opcode == DP4A_OP), - "only cvt, set, slct, tex and dp4a can have more than one " + (g_opcode == DP4A_OP) || (g_opcode == VMIN_OP) || + (g_opcode == VMAX_OP), + "only cvt, set, slct, tex, vmin, vmax and dp4a can have more than one " "type specifier."); } g_scalar_type_spec = type_spec; |
